Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
36 changes: 28 additions & 8 deletions cmd/sin-code/internal/superpowers/superpowers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ var DefaultRepoURL = "https://github.com/obra/superpowers.git"
// 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
)

// 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 +69,7 @@ func Home() string {
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 +144,25 @@ func Install(ctx context.Context, repoURL, branch string) (*InstallResult, error
}
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
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
2 changes: 1 addition & 1 deletion cmd/sin-code/internal/vane/mcpserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (s *Server) dispatch(ctx context.Context, req *jsonRPCRequest) *jsonRPCResp
}

func (s *Server) result(req *jsonRPCRequest, v any) *jsonRPCResponse {
data, err := json.Marshal(v)
data, err := jsonMarshalFn(v)
if err != nil {
return &jsonRPCResponse{
JSONRPC: "2.0",
Expand Down
35 changes: 26 additions & 9 deletions cmd/sin-code/internal/vane/vane.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@
"github.com/OpenSIN-Code/SIN-Code/cmd/sin-code/internal/circuitbreaker"
)

// testHook variables allow tests to inject failure without heavy
// refactoring. They are package-level vars (not build-tagged) so the
// production binary pays only the indirection cost.
var (
osUserHomeDirFn = os.UserHomeDir
osExecutableFn = os.Executable
jsonMarshalFn = json.Marshal
jsonMarshalIndentFn = json.MarshalIndent
ioCopyNFn = io.CopyN
ioReadAllFn = io.ReadAll
osMkdirAllFn = os.MkdirAll
osCreateTempFn = os.CreateTemp
writeJSONCopyFn = io.Copy
writeJSONWriteFn = func(w io.Writer, p []byte) (int, error) { return w.Write(p) }
writeJSONCloseFn = func(c io.Closer) error { return c.Close() }
)

// ── Public configuration constants ─────────────────────────────────────

// ServerName is the MCP server name registered in mcp.json. Used by
Expand Down Expand Up @@ -62,7 +79,7 @@
return v
}
// Use os.UserHomeDir for cross-platform safety (macOS/Linux/Windows).
if h, err := os.UserHomeDir(); err == nil {
if h, err := osUserHomeDirFn(); err == nil {
return filepath.Join(h, ".local", "share", "sin-code")
}
// Last resort: cwd-relative fallback so the function is total.
Expand Down Expand Up @@ -430,28 +447,28 @@
// directories are created on demand. Mirrors superpowers.WriteJSON() so
// the rest of the codebase has a consistent persistence semantic.
func writeJSONAtomic(path string, v any) error {
data, err := json.MarshalIndent(v, "", " ")
data, err := jsonMarshalIndentFn(v, "", " ")
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
if err := osMkdirAllFn(filepath.Dir(path), 0o755); err != nil {
return err
}
tmp, err := os.CreateTemp(filepath.Dir(path), ".vane-*.json.tmp")
tmp, err := osCreateTempFn(filepath.Dir(path), ".vane-*.json.tmp")
if err != nil {
return err
}
tmpName := tmp.Name()
defer os.Remove(tmpName)
if _, err := io.Copy(tmp, bytes.NewReader(data)); err != nil {
tmp.Close()
if _, err := writeJSONCopyFn(tmp, bytes.NewReader(data)); err != nil {
writeJSONCloseFn(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 := writeJSONWriteFn(tmp, []byte("\n")); err != nil {
writeJSONCloseFn(tmp)

Check warning

Code scanning / gosec

Errors unhandled Warning

Errors unhandled
return err
}
if err := tmp.Close(); err != nil {
if err := writeJSONCloseFn(tmp); err != nil {
return err
}
return os.Rename(tmpName, path)
Expand Down
17 changes: 14 additions & 3 deletions cmd/sin-code/tui/agent_runner_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package tui

import (
"context"
"fmt"
"strings"

Expand All @@ -30,6 +31,16 @@
// initAgentRunner lazily initializes the agent runner used for chat
// submits. Returns the runner or nil if it could not be constructed.
// The caller is responsible for calling Close() when the TUI exits.
// newAgentRunnerHook is a test seam for AgentRunner construction.
var newAgentRunnerHook = func(ctx context.Context, cfg agentrunner.Config) (*agentrunner.AgentRunner, error) {
return agentrunner.NewAgentRunner(ctx, cfg)
}

// submitAgentRunnerHook is a test seam for AgentRunner submission.
var submitAgentRunnerHook = func(r *agentrunner.AgentRunner, ctx context.Context, prompt string) (string, error) {
return r.Submit(ctx, prompt)

Check failure on line 41 in cmd/sin-code/tui/agent_runner_adapter.go

View workflow job for this annotation

GitHub Actions / govulncheck

cannot use r.Submit(ctx, prompt) (value of type <-chan struct{}) as string value in return statement
}

func (m *Model) initAgentRunner() *agentrunner.AgentRunner {
if m.AgentRunner != nil {
return m.AgentRunner
Expand All @@ -38,7 +49,7 @@
if ws == "" {
ws = "."
}
r, err := agentrunner.NewAgentRunner(m.ctx(), agentrunner.Config{
r, err := newAgentRunnerHook(m.ctx(), agentrunner.Config{
Workspace: ws,
Headless: false, // TUI is interactive — show the Ask dialog
Yolo: false, // never auto-allow in interactive mode
Expand Down Expand Up @@ -122,7 +133,7 @@
if r == nil {
return nil
}
if _, err := r.Submit(m.ctx(), prompt); err != nil {
if _, err := submitAgentRunnerHook(r, m.ctx(), prompt); err != nil {
m.ChatHistory = append(m.ChatHistory,
"assistant: (agent runner unavailable: "+err.Error()+")")
if len(m.ChatHistory) > 500 {
Expand Down Expand Up @@ -151,7 +162,7 @@
return nil
}
prompt := fmt.Sprintf("use the %s tool to %s", skill, args)
if _, err := r.Submit(m.ctx(), prompt); err != nil {
if _, err := submitAgentRunnerHook(r, m.ctx(), prompt); err != nil {
m.ChatHistory = append(m.ChatHistory,
"assistant: (agent runner error: "+err.Error()+")")
if len(m.ChatHistory) > 500 {
Expand Down
2 changes: 1 addition & 1 deletion cmd/sin-code/tui/chat/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@
return false
}
if strings.HasPrefix(trimmed, "~/") {
home, err := os.UserHomeDir()
home, err := osUserHomeDirHook()

Check failure on line 282 in cmd/sin-code/tui/chat/input.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: osUserHomeDirHook (typecheck)

Check failure on line 282 in cmd/sin-code/tui/chat/input.go

View workflow job for this annotation

GitHub Actions / verify

undefined: osUserHomeDirHook

Check failure on line 282 in cmd/sin-code/tui/chat/input.go

View workflow job for this annotation

GitHub Actions / govulncheck

undefined: osUserHomeDirHook

Check failure on line 282 in cmd/sin-code/tui/chat/input.go

View workflow job for this annotation

GitHub Actions / go test

undefined: osUserHomeDirHook
if err != nil {
return false
}
Expand Down
7 changes: 6 additions & 1 deletion cmd/sin-code/tui/chat/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import (
"github.com/OpenSIN-Code/SIN-Code/cmd/sin-code/internal/llm"
)

var (
// providerFromConfigHook is overridden in tests to exercise NewRunner error paths.
providerFromConfigHook = llm.ProviderFromConfig
)

const (
defaultModel = "meta/llama-3.3-70b-instruct"
defaultSystem = "You are sin-code, an AI coding assistant. Be concise."
Expand All @@ -37,7 +42,7 @@ func NewRunner() (*Runner, error) {
if os.Getenv("SIN_NIM_API_KEY") == "" {
return nil, fmt.Errorf("no API key configured (set SIN_NIM_API_KEY)")
}
c, err := llm.ProviderFromConfig("nim", "", "", defaultModel, 0)
c, err := providerFromConfigHook("nim", "", "", defaultModel, 0)
if err != nil {
return nil, err
}
Expand Down
10 changes: 9 additions & 1 deletion cmd/sin-code/tui/chat_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@

type chatInput = chat.Input

// newChatRunnerHook is a test seam for chat runner construction.
var newChatRunnerHook = func() (*chat.Runner, error) { return chat.NewRunner() }

// chatRunnerRunHook is a test seam for chat runner execution.
var chatRunnerRunHook = func(r *chat.Runner, ctx context.Context, prompt string, history []string) (string, error) {

Check failure on line 21 in cmd/sin-code/tui/chat_input.go

View workflow job for this annotation

GitHub Actions / govulncheck

undefined: context
return r.Run(ctx, prompt, history)
}

func newChatInput() *chatInput {
store, err := attachments.NewStore()
if err != nil {
Expand All @@ -35,7 +43,7 @@
if m.ChatRunner != nil {
return
}
r, err := chat.NewRunner()
r, err := newChatRunnerHook()
if err != nil {
m.ChatRunner = nil
return
Expand Down
4 changes: 2 additions & 2 deletions cmd/sin/skill_cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func runSkillValidate(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("parse error: %w", err)
}

var errors []string
if skill.Name == "" {
errors = append(errors, "missing skill name (first heading)")
Expand All @@ -182,7 +182,7 @@ func runSkillValidate(cmd *cobra.Command, args []string) error {
if _, ok := skill.Sections["Anti-Rationalization"]; !ok {
errors = append(errors, "missing ## Anti-Rationalization section (recommended)")
}

if len(errors) > 0 {
fmt.Printf("❌ Validation failed for %s:\n", path)
for _, e := range errors {
Expand Down
14 changes: 7 additions & 7 deletions internal/headroom/compressor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import (
// Compressor is the main entry point for headroom compression in SIN-Code.
// It automatically selects the best available mode (MCP > CLI > disabled).
type Compressor struct {
config Config
mode Mode
cliCli *CLIClient
mcpCli *MCPClient
lessons *LessonStore
enabled bool
stats atomic.Value // stores *Stats
config Config
mode Mode
cliCli *CLIClient
mcpCli *MCPClient
lessons *LessonStore
enabled bool
stats atomic.Value // stores *Stats
}

// SetLessonStore attaches a lesson store so that LearnFromFailure persists
Expand Down
10 changes: 5 additions & 5 deletions internal/headroom/lessons.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import (
// that previously turned out to be important.
type Lesson struct {
ID string `json:"id"`
Category string `json:"category"` // e.g. "compression", "retrieval", "tooling"
Pattern string `json:"pattern"` // the content pattern that mattered
Insight string `json:"insight"` // what was learned
Weight float64 `json:"weight"` // importance 0..1, higher = keep more
Hits int `json:"hits"` // how often this lesson was reinforced
Category string `json:"category"` // e.g. "compression", "retrieval", "tooling"
Pattern string `json:"pattern"` // the content pattern that mattered
Insight string `json:"insight"` // what was learned
Weight float64 `json:"weight"` // importance 0..1, higher = keep more
Hits int `json:"hits"` // how often this lesson was reinforced
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Expand Down
Loading
Loading