Function bodies 82 total
main.main function · go · L22-L40 (19 LOC)cmd/orc/main.go
func main() {
app := &cli.Command{
Name: "orc",
Usage: "Deterministic agent orchestrator",
Description: "Run 'orc docs' for documentation on config syntax, variables, phases, and more.",
Commands: []*cli.Command{
initCmd(),
runCmd(),
statusCmd(),
doctorCmd(),
docsCmd(),
},
}
if err := app.Run(context.Background(), os.Args); err != nil {
fmt.Fprintf(os.Stderr, "%serror:%s %v\n", ux.Red, ux.Reset, err)
os.Exit(1)
}
}main.runCmd function · go · L42-L163 (122 LOC)cmd/orc/main.go
func runCmd() *cli.Command {
return &cli.Command{
Name: "run",
Usage: "Run the workflow for a ticket",
ArgsUsage: "<ticket>",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "auto", Usage: "Skip human gates"},
&cli.IntFlag{Name: "retry", Usage: "Retry from phase N (1-indexed)"},
&cli.IntFlag{Name: "from", Usage: "Start from phase N (1-indexed)"},
&cli.BoolFlag{Name: "dry-run", Usage: "Print phase plan without executing"},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
// CLAUDECODE guard
if os.Getenv("CLAUDECODE") != "" {
return fmt.Errorf("orc cannot run inside Claude Code (CLAUDECODE env var is set). Run from a regular terminal")
}
ticket := cmd.Args().First()
if ticket == "" {
return fmt.Errorf("ticket argument is required")
}
projectRoot, err := findProjectRoot()
if err != nil {
return err
}
configPath := filepath.Join(projectRoot, ".orc", "config.yaml")
cfg, err := config.Load(configPath, projmain.statusCmd function · go · L165-L201 (37 LOC)cmd/orc/main.go
func statusCmd() *cli.Command {
return &cli.Command{
Name: "status",
Usage: "Show workflow status for a ticket",
ArgsUsage: "<ticket>",
Action: func(ctx context.Context, cmd *cli.Command) error {
ticket := cmd.Args().First()
if ticket == "" {
return fmt.Errorf("ticket argument is required")
}
projectRoot, err := findProjectRoot()
if err != nil {
return err
}
configPath := filepath.Join(projectRoot, ".orc", "config.yaml")
cfg, err := config.Load(configPath, projectRoot)
if err != nil {
return fmt.Errorf("loading config: %w", err)
}
artifactsDir := filepath.Join(projectRoot, ".orc", "artifacts")
st, err := state.Load(artifactsDir)
if err != nil {
return fmt.Errorf("loading state: %w", err)
}
if st.Ticket != "" && st.Ticket != ticket {
return fmt.Errorf("state is for ticket %q, not %q", st.Ticket, ticket)
}
ux.RenderStatus(cfg, st, artifactsDir)
return nil
},
}
}main.doctorCmd function · go · L203-L228 (26 LOC)cmd/orc/main.go
func doctorCmd() *cli.Command {
return &cli.Command{
Name: "doctor",
Usage: "Diagnose a failed workflow run using AI",
Action: func(ctx context.Context, cmd *cli.Command) error {
projectRoot, err := findProjectRoot()
if err != nil {
return err
}
configPath := filepath.Join(projectRoot, ".orc", "config.yaml")
cfg, err := config.Load(configPath, projectRoot)
if err != nil {
return fmt.Errorf("loading config: %w", err)
}
artifactsDir := filepath.Join(projectRoot, ".orc", "artifacts")
st, err := state.Load(artifactsDir)
if err != nil {
return fmt.Errorf("loading state: %w", err)
}
return doctor.Run(ctx, projectRoot, artifactsDir, cfg, st)
},
}
}main.initCmd function · go · L230-L242 (13 LOC)cmd/orc/main.go
func initCmd() *cli.Command {
return &cli.Command{
Name: "init",
Usage: "Initialize a new .orc/ directory with example config",
Action: func(ctx context.Context, cmd *cli.Command) error {
dir, err := os.Getwd()
if err != nil {
return err
}
return scaffold.Init(ctx, dir)
},
}
}main.docsCmd function · go · L244-L267 (24 LOC)cmd/orc/main.go
func docsCmd() *cli.Command {
return &cli.Command{
Name: "docs",
Usage: "Show documentation",
ArgsUsage: "[topic]",
Action: func(ctx context.Context, cmd *cli.Command) error {
name := cmd.Args().First()
if name == "" {
fmt.Print("\nAvailable topics:\n\n")
for _, t := range docs.All() {
fmt.Printf(" %-14s %s\n", t.Name, t.Summary)
}
fmt.Println("\nRun 'orc docs <topic>' to read a topic.")
return nil
}
t, err := docs.Get(name)
if err != nil {
return err
}
fmt.Print(t.Content)
return nil
},
}
}main.findProjectRoot function · go · L270-L286 (17 LOC)cmd/orc/main.go
func findProjectRoot() (string, error) {
dir, err := os.Getwd()
if err != nil {
return "", err
}
for {
configPath := filepath.Join(dir, ".orc", "config.yaml")
if _, err := os.Stat(configPath); err == nil {
return dir, nil
}
parent := filepath.Dir(dir)
if parent == dir {
return "", fmt.Errorf("no .orc/config.yaml found (searched from cwd to root)")
}
dir = parent
}
}Repobility · open methodology · https://repobility.com/research/
config.OrderedVars.UnmarshalYAML method · go · L41-L60 (20 LOC)internal/config/config.go
func (ov *OrderedVars) UnmarshalYAML(value *yaml.Node) error {
if value.Kind != yaml.MappingNode {
return fmt.Errorf("config: vars: must be a mapping")
}
for i := 0; i < len(value.Content)-1; i += 2 {
keyNode := value.Content[i]
valNode := value.Content[i+1]
if keyNode.Kind != yaml.ScalarNode {
return fmt.Errorf("config: vars: key at position %d is not a scalar", i/2+1)
}
if valNode.Kind != yaml.ScalarNode {
return fmt.Errorf("config: vars: value for %q is not a scalar (nested maps/sequences are not supported)", keyNode.Value)
}
*ov = append(*ov, VarEntry{
Key: keyNode.Value,
Value: valNode.Value,
})
}
return nil
}config.Load function · go · L70-L83 (14 LOC)internal/config/config.go
func Load(path, projectRoot string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, err
}
if err := Validate(&cfg, projectRoot); err != nil {
return nil, err
}
return &cfg, nil
}config.Config.PhaseIndex method · go · L86-L93 (8 LOC)internal/config/config.go
func (c *Config) PhaseIndex(name string) int {
for i, p := range c.Phases {
if p.Name == name {
return i
}
}
return -1
}config.Validate function · go · L21-L150 (130 LOC)internal/config/validate.go
func Validate(cfg *Config, projectRoot string) error {
if cfg.Name == "" {
return fmt.Errorf("config: 'name' is required")
}
if len(cfg.Phases) == 0 {
return fmt.Errorf("config: at least one phase is required")
}
// Validate vars
builtins := map[string]bool{
"TICKET": true, "ARTIFACTS_DIR": true,
"WORK_DIR": true, "PROJECT_ROOT": true,
"PHASE_INDEX": true, "PHASE_COUNT": true,
}
seenVars := make(map[string]bool)
for _, v := range cfg.Vars {
if v.Key == "" {
return fmt.Errorf("config: vars: empty variable name")
}
if !varNameRe.MatchString(v.Key) {
return fmt.Errorf("config: vars: %q is not a valid variable name (must match [A-Za-z_][A-Za-z0-9_]*)", v.Key)
}
if builtins[v.Key] {
return fmt.Errorf("config: vars: %q overrides a built-in variable", v.Key)
}
if seenVars[v.Key] {
return fmt.Errorf("config: vars: duplicate variable %q", v.Key)
}
seenVars[v.Key] = true
}
seen := make(map[string]bool)
for i := range cfg.Phases {
p := &cfg.config.ValidateTicket function · go · L154-L171 (18 LOC)internal/config/validate.go
func ValidateTicket(pattern, ticket string) error {
if pattern == "" {
return nil
}
// Enforce full-match semantics: anchor the pattern if not already anchored.
anchored := pattern
if !strings.HasPrefix(anchored, "^") {
anchored = "^(?:" + anchored + ")$"
}
re, err := regexp.Compile(anchored)
if err != nil {
return fmt.Errorf("config: invalid ticket-pattern %q: %w", pattern, err)
}
if !re.MatchString(ticket) {
return fmt.Errorf("ticket %q does not match pattern %q", ticket, pattern)
}
return nil
}config.phaseExists function · go · L173-L180 (8 LOC)internal/config/validate.go
func phaseExists(phases []Phase, name string) bool {
for _, p := range phases {
if p.Name == name {
return true
}
}
return false
}contextgather.Gather function · go · L55-L65 (11 LOC)internal/contextgather/gather.go
func Gather(projectRoot string) (*ProjectContext, error) {
pc := &ProjectContext{
Files: make(map[string]string),
}
pc.DirTree = buildTree(projectRoot)
gatherFiles(projectRoot, pc)
pc.GitLog = gatherGitLog(projectRoot)
return pc, nil
}contextgather.ProjectContext.Render method · go · L68-L97 (30 LOC)internal/contextgather/gather.go
func (pc *ProjectContext) Render() string {
var buf strings.Builder
buf.WriteString("## Project Directory Structure\n\n```\n")
buf.WriteString(pc.DirTree)
buf.WriteString("```\n")
if len(pc.Files) > 0 {
buf.WriteString("\n## Key Files\n")
// Sort paths for deterministic output
paths := make([]string, 0, len(pc.Files))
for p := range pc.Files {
paths = append(paths, p)
}
sort.Strings(paths)
for _, p := range paths {
buf.WriteString(fmt.Sprintf("\n### %s\n\n```\n%s\n```\n", p, pc.Files[p]))
}
}
if pc.GitLog != "" {
buf.WriteString("\n## Recent Git History\n\n```\n")
buf.WriteString(pc.GitLog)
buf.WriteString("```\n")
}
return buf.String()
}Repobility — same analyzer, your code, free for public repos · /scan/
contextgather.buildTree function · go · L99-L130 (32 LOC)internal/contextgather/gather.go
func buildTree(root string) string {
entries, err := os.ReadDir(root)
if err != nil {
return "(unable to read directory)\n"
}
var buf strings.Builder
for _, e := range entries {
if skipDirs[e.Name()] {
continue
}
if e.IsDir() {
buf.WriteString(e.Name() + "/\n")
// One level deeper
subPath := filepath.Join(root, e.Name())
subEntries, err := os.ReadDir(subPath)
if err != nil {
continue
}
for _, se := range subEntries {
if se.IsDir() {
buf.WriteString(" " + se.Name() + "/\n")
} else {
buf.WriteString(" " + se.Name() + "\n")
}
}
} else {
buf.WriteString(e.Name() + "\n")
}
}
return buf.String()
}contextgather.gatherFiles function · go · L132-L169 (38 LOC)internal/contextgather/gather.go
func gatherFiles(root string, pc *ProjectContext) {
// Direct file probes
for _, name := range wellKnownFiles {
path := filepath.Join(root, name)
data, err := os.ReadFile(path)
if err != nil {
continue
}
content := string(data)
if len(content) > maxFileSize {
content = content[:maxFileSize] + "\n... (truncated)"
}
pc.Files[name] = content
}
// Glob patterns
for _, pattern := range wellKnownGlobs {
matches, err := filepath.Glob(filepath.Join(root, pattern))
if err != nil {
continue
}
for _, match := range matches {
data, err := os.ReadFile(match)
if err != nil {
continue
}
rel, err := filepath.Rel(root, match)
if err != nil {
continue
}
content := string(data)
if len(content) > maxFileSize {
content = content[:maxFileSize] + "\n... (truncated)"
}
pc.Files[rel] = content
}
}
}contextgather.gatherGitLog function · go · L171-L179 (9 LOC)internal/contextgather/gather.go
func gatherGitLog(root string) string {
cmd := exec.Command("git", "log", "--oneline", "-10")
cmd.Dir = root
out, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}dispatch.buildAgentArgs function · go · L24-L50 (27 LOC)internal/dispatch/agent.go
func buildAgentArgs(phase config.Phase, prompt, sessionID string, isFirst bool, extraTools []string) []string {
args := []string{"-p", prompt,
"--output-format", "stream-json",
"--verbose",
"--include-partial-messages",
"--model", phase.Model,
}
if sessionID != "" {
if isFirst {
args = append(args, "--session-id", sessionID)
} else {
args = append(args, "--resume", sessionID)
}
}
// Merge phase allow-tools with any dynamically approved tools
tools := make([]string, 0, len(phase.AllowTools)+len(extraTools))
tools = append(tools, phase.AllowTools...)
tools = append(tools, extraTools...)
if len(tools) > 0 {
args = append(args, "--allowedTools")
args = append(args, tools...)
}
return args
}dispatch.runAgentTurn function · go · L59-L92 (34 LOC)internal/dispatch/agent.go
func runAgentTurn(ctx context.Context, phase config.Phase, env *Environment, prompt, sessionID string, isFirst bool, logFile io.Writer, extraTools []string) (*turnResult, error) {
args := buildAgentArgs(phase, prompt, sessionID, isFirst, extraTools)
cmd := exec.CommandContext(ctx, "claude", args...)
cmd.Dir = PhaseWorkDir(phase, env)
cmd.Env = BuildEnv(env)
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Cancel = func() error {
return syscall.Kill(-cmd.Process.Pid, syscall.SIGTERM)
}
cmd.WaitDelay = 5 * time.Second
cmd.Stderr = io.MultiWriter(os.Stderr, logFile)
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("stdout pipe: %w", err)
}
if err := cmd.Start(); err != nil {
return nil, fmt.Errorf("starting claude: %w", err)
}
streamResult, streamErr := processStream(ctx, stdout, os.Stdout, logFile)
code, waitErr := exitCode(cmd.Wait())
if waitErr != nil {
return nil, waitErr
}
if streamErr != nil && ctx.Err() == nil {
returdispatch.RunAgent function · go · L96-L141 (46 LOC)internal/dispatch/agent.go
func RunAgent(ctx context.Context, phase config.Phase, env *Environment) (*Result, error) {
if phase.Timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, time.Duration(phase.Timeout)*time.Minute)
defer cancel()
}
// Read and render the prompt template
promptData, err := os.ReadFile(filepath.Join(env.ProjectRoot, phase.Prompt))
if err != nil {
return nil, err
}
rendered := ExpandVars(string(promptData), env.Vars())
// Save rendered prompt for inspection
if err := os.WriteFile(state.PromptPath(env.ArtifactsDir, env.PhaseIndex), []byte(rendered), 0644); err != nil {
return nil, err
}
logFile, err := os.OpenFile(state.LogPath(env.ArtifactsDir, env.PhaseIndex), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return nil, err
}
defer logFile.Close()
sessionID := uuid.New().String()
tr, err := runAgentTurn(ctx, phase, env, rendered, sessionID, true, logFile, nil)
if err != nil {
return nil, err
}
// In unattended moddispatch.RunAgentWithPrompt function · go · L145-L168 (24 LOC)internal/dispatch/agent.go
func RunAgentWithPrompt(ctx context.Context, phase config.Phase, env *Environment, prompt string) (*Result, error) {
if phase.Timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, time.Duration(phase.Timeout)*time.Minute)
defer cancel()
}
logFile, err := os.OpenFile(state.LogPath(env.ArtifactsDir, env.PhaseIndex), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nil, err
}
defer logFile.Close()
tr, err := runAgentTurn(ctx, phase, env, prompt, "", false, logFile, nil)
if err != nil {
return nil, err
}
output := ""
if tr.Stream != nil {
output = tr.Stream.Text
}
return &Result{ExitCode: tr.ExitCode, Output: output}, nil
}dispatch.RunAgentAttended function · go · L175-L247 (73 LOC)internal/dispatch/agent.go
func RunAgentAttended(ctx context.Context, phase config.Phase, env *Environment) (*Result, error) {
if phase.Timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, time.Duration(phase.Timeout)*time.Minute)
defer cancel()
}
// Read and render the prompt template
promptData, err := os.ReadFile(filepath.Join(env.ProjectRoot, phase.Prompt))
if err != nil {
return nil, err
}
rendered := ExpandVars(string(promptData), env.Vars())
// Save rendered prompt for inspection
if err := os.WriteFile(state.PromptPath(env.ArtifactsDir, env.PhaseIndex), []byte(rendered), 0644); err != nil {
return nil, err
}
logFile, err := os.OpenFile(state.LogPath(env.ArtifactsDir, env.PhaseIndex), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return nil, err
}
defer logFile.Close()
sessionID := uuid.New().String()
reader := NewStdinReader(os.Stdin)
defer reader.Stop()
var extraTools []string
isFirst := true
prompt := rendered
var lastTurn *Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
dispatch.handleDenials function · go · L251-L273 (23 LOC)internal/dispatch/agent.go
func handleDenials(denials []PermissionDenial) []string {
var names []string
for _, d := range denials {
names = append(names, d.String())
ux.ToolDenied(d.Tool, d.Input)
}
ux.PermissionPrompt(names)
fmt.Printf(" Retry with these tools approved? [y/n]: ")
scanner := bufio.NewScanner(os.Stdin)
if scanner.Scan() {
answer := strings.TrimSpace(strings.ToLower(scanner.Text()))
if answer == "y" || answer == "yes" {
var tools []string
for _, d := range denials {
tools = append(tools, d.Tool)
}
return tools
}
}
return nil
}dispatch.Environment.Clone method · go · L26-L39 (14 LOC)internal/dispatch/dispatch.go
func (e *Environment) Clone() *Environment {
cp := *e
if e.CustomVars != nil {
cp.CustomVars = make(map[string]string, len(e.CustomVars))
for k, v := range e.CustomVars {
cp.CustomVars[k] = v
}
}
if e.filteredEnv != nil {
cp.filteredEnv = make([]string, len(e.filteredEnv))
copy(cp.filteredEnv, e.filteredEnv)
}
return &cp
}dispatch.Environment.Vars method · go · L43-L53 (11 LOC)internal/dispatch/dispatch.go
func (e *Environment) Vars() map[string]string {
m := make(map[string]string, 4+len(e.CustomVars))
for k, v := range e.CustomVars {
m[k] = v
}
m["TICKET"] = e.Ticket
m["ARTIFACTS_DIR"] = e.ArtifactsDir
m["WORK_DIR"] = e.WorkDir
m["PROJECT_ROOT"] = e.ProjectRoot
return m
}dispatch.PhaseWorkDir function · go · L58-L67 (10 LOC)internal/dispatch/dispatch.go
func PhaseWorkDir(phase config.Phase, env *Environment) string {
if phase.Cwd != "" {
expanded := ExpandVars(phase.Cwd, env.Vars())
if expanded == "" {
return env.WorkDir
}
return expanded
}
return env.WorkDir
}dispatch.BuildEnv function · go · L78-L102 (25 LOC)internal/dispatch/dispatch.go
func BuildEnv(env *Environment) []string {
if env.filteredEnv == nil {
for _, e := range os.Environ() {
key := strings.SplitN(e, "=", 2)[0]
if strings.HasPrefix(key, "CLAUDECODE") {
continue
}
env.filteredEnv = append(env.filteredEnv, e)
}
}
result := make([]string, len(env.filteredEnv), len(env.filteredEnv)+6+len(env.CustomVars))
copy(result, env.filteredEnv)
for k, v := range env.CustomVars {
result = append(result, "ORC_"+k+"="+v)
}
result = append(result,
"ORC_TICKET="+env.Ticket,
"ORC_ARTIFACTS_DIR="+env.ArtifactsDir,
"ORC_WORK_DIR="+env.WorkDir,
"ORC_PROJECT_ROOT="+env.ProjectRoot,
fmt.Sprintf("ORC_PHASE_INDEX=%d", env.PhaseIndex),
fmt.Sprintf("ORC_PHASE_COUNT=%d", env.PhaseCount),
)
return result
}dispatch.Dispatch function · go · L118-L132 (15 LOC)internal/dispatch/dispatch.go
func Dispatch(ctx context.Context, phase config.Phase, env *Environment) (*Result, error) {
switch phase.Type {
case "script":
return RunScript(ctx, phase, env)
case "agent":
if env.AutoMode {
return RunAgent(ctx, phase, env)
}
return RunAgentAttended(ctx, phase, env)
case "gate":
return RunGate(ctx, phase, env)
default:
return nil, fmt.Errorf("unknown phase type: %s", phase.Type)
}
}dispatch.exitCode function · go · L10-L19 (10 LOC)internal/dispatch/exitcode.go
func exitCode(err error) (int, error) {
if err == nil {
return 0, nil
}
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
return exitErr.ExitCode(), nil
}
return 0, err
}dispatch.ExpandVars function · go · L11-L18 (8 LOC)internal/dispatch/expand.go
func ExpandVars(template string, vars map[string]string) string {
return os.Expand(template, func(key string) string {
if v, ok := vars[key]; ok {
return v
}
return os.Getenv(key)
})
}Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
dispatch.ExpandConfigVars function · go · L22-L34 (13 LOC)internal/dispatch/expand.go
func ExpandConfigVars(vars config.OrderedVars, builtins map[string]string) map[string]string {
result := make(map[string]string, len(vars))
lookup := make(map[string]string, len(builtins)+len(vars))
for k, v := range builtins {
lookup[k] = v
}
for _, entry := range vars {
expanded := ExpandVars(entry.Value, lookup)
result[entry.Key] = expanded
lookup[entry.Key] = expanded
}
return result
}dispatch.RunGate function · go · L15-L73 (59 LOC)internal/dispatch/gate.go
func RunGate(ctx context.Context, phase config.Phase, env *Environment) (*Result, error) {
logFile, err := os.Create(state.LogPath(env.ArtifactsDir, env.PhaseIndex))
if err != nil {
return nil, err
}
defer logFile.Close()
// Auto-approve if --auto mode
if env.AutoMode {
msg := fmt.Sprintf("Gate %q auto-approved (--auto mode)\n", phase.Name)
fmt.Print(msg)
logFile.WriteString(msg)
return &Result{ExitCode: 0, Output: msg}, nil
}
// Show gate description
if phase.Description != "" {
fmt.Printf("\n %s\n\n", phase.Description)
}
// Prompt user
fmt.Printf(" Approve? [y/n]: ")
reader := bufio.NewReader(os.Stdin)
// Use a channel to handle context cancellation during read
type readResult struct {
input string
err error
}
ch := make(chan readResult, 1)
go func() {
line, err := reader.ReadString('\n')
ch <- readResult{input: strings.TrimSpace(line), err: err}
}()
select {
case <-ctx.Done():
msg := "Gate cancelled\n"
logFile.WriteString(msg)
dispatch.Preflight function · go · L12-L34 (23 LOC)internal/dispatch/preflight.go
func Preflight(phases []config.Phase) error {
needed := make(map[string]bool)
for _, p := range phases {
switch p.Type {
case "script":
needed["bash"] = true
case "agent":
needed["claude"] = true
}
}
var missing []string
for bin := range needed {
if _, err := exec.LookPath(bin); err != nil {
missing = append(missing, bin)
}
}
if len(missing) > 0 {
return fmt.Errorf("required binaries not found in PATH: %s", strings.Join(missing, ", "))
}
return nil
}dispatch.RunScript function · go · L17-L51 (35 LOC)internal/dispatch/script.go
func RunScript(ctx context.Context, phase config.Phase, env *Environment) (*Result, error) {
if phase.Timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, time.Duration(phase.Timeout)*time.Minute)
defer cancel()
}
expanded := ExpandVars(phase.Run, env.Vars())
cmd := exec.CommandContext(ctx, "bash", "-c", expanded)
cmd.Dir = PhaseWorkDir(phase, env)
cmd.Env = BuildEnv(env)
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Cancel = func() error {
return syscall.Kill(-cmd.Process.Pid, syscall.SIGTERM)
}
cmd.WaitDelay = 5 * time.Second
logFile, err := os.Create(state.LogPath(env.ArtifactsDir, env.PhaseIndex))
if err != nil {
return nil, err
}
defer logFile.Close()
var captured bytes.Buffer
cmd.Stdout = io.MultiWriter(os.Stdout, logFile, &captured)
cmd.Stderr = io.MultiWriter(os.Stderr, logFile, &captured)
code, err := exitCode(cmd.Run())
if err != nil {
return nil, err
}
return &Result{ExitCode: code, Output: captdispatch.NewStdinReader function · go · L17-L24 (8 LOC)internal/dispatch/stdinreader.go
func NewStdinReader(r io.Reader) *StdinReader {
sr := &StdinReader{
lines: make(chan string, 16),
done: make(chan struct{}),
}
go sr.readLoop(r)
return sr
}dispatch.StdinReader.readLoop method · go · L26-L47 (22 LOC)internal/dispatch/stdinreader.go
func (sr *StdinReader) readLoop(r io.Reader) {
scanner := bufio.NewScanner(r)
for {
select {
case <-sr.done:
return
default:
}
if !scanner.Scan() {
return
}
line := scanner.Text()
if line == "" {
continue
}
select {
case sr.lines <- line:
case <-sr.done:
return
}
}
}dispatch.StdinReader.ReadLine method · go · L51-L58 (8 LOC)internal/dispatch/stdinreader.go
func (sr *StdinReader) ReadLine() (string, bool) {
select {
case line := <-sr.lines:
return line, true
default:
return "", false
}
}dispatch.StdinReader.Stop method · go · L63-L70 (8 LOC)internal/dispatch/stdinreader.go
func (sr *StdinReader) Stop() {
select {
case <-sr.done:
// already stopped
default:
close(sr.done)
}
}Repobility · open methodology · https://repobility.com/research/
dispatch.PermissionDenial.String method · go · L21-L26 (6 LOC)internal/dispatch/stream.go
func (d PermissionDenial) String() string {
if d.Input != "" {
return fmt.Sprintf("%s(%s)", d.Tool, d.Input)
}
return d.Tool
}dispatch.processStream function · go · L38-L82 (45 LOC)internal/dispatch/stream.go
func processStream(ctx context.Context, stdout io.Reader, display io.Writer, logFile io.Writer) (*StreamResult, error) {
scanner := bufio.NewScanner(stdout)
scanner.Buffer(make([]byte, 0, 256*1024), 1024*1024)
var result StreamResult
var textBuf strings.Builder
for scanner.Scan() {
if ctx.Err() != nil {
return &result, ctx.Err()
}
line := scanner.Bytes()
if len(line) == 0 {
continue
}
var event streamEvent
if err := json.Unmarshal(line, &event); err != nil {
// Skip malformed lines
continue
}
switch event.Type {
case "stream_event":
handleStreamEvent(&event, &textBuf, display, logFile)
case "assistant":
handleAssistantEvent(&event)
case "user":
handleUserEvent(&event, &result)
case "result":
handleResultEvent(&event, &result)
}
}
if err := scanner.Err(); err != nil {
return &result, fmt.Errorf("reading stream: %w", err)
}
result.Text = textBuf.String()
return &result, nil
}dispatch.handleStreamEvent function · go · L134-L166 (33 LOC)internal/dispatch/stream.go
func handleStreamEvent(event *streamEvent, textBuf *strings.Builder, display io.Writer, logFile io.Writer) {
if event.Event == nil {
return
}
var nested nestedEvent
if err := json.Unmarshal(event.Event, &nested); err != nil {
return
}
switch nested.Type {
case "content_block_delta":
if nested.Delta != nil && nested.Delta.Type == "text_delta" {
text := nested.Delta.Text
textBuf.WriteString(text)
if display != nil {
fmt.Fprint(display, text)
}
if logFile != nil {
fmt.Fprint(logFile, text)
}
}
case "content_block_start":
if nested.ContentBlock != nil && nested.ContentBlock.Type == "tool_use" {
inputStr := ""
if nested.ContentBlock.Input != nil {
inputStr = string(nested.ContentBlock.Input)
}
ux.ToolUse(nested.ContentBlock.Name, inputStr)
}
}
}dispatch.handleUserEvent function · go · L174-L183 (10 LOC)internal/dispatch/stream.go
func handleUserEvent(event *streamEvent, result *StreamResult) {
if event.IsError {
// Permission denial or other error from the user side
for _, block := range event.Content {
if strings.Contains(block.Text, "permission") || strings.Contains(block.Text, "denied") {
// The actual denials are in the result event; this is just a signal
}
}
}
}dispatch.handleResultEvent function · go · L185-L209 (25 LOC)internal/dispatch/stream.go
func handleResultEvent(event *streamEvent, result *StreamResult) {
// Try to parse the nested result object
if event.Result != nil {
var payload resultPayload
if err := json.Unmarshal(event.Result, &payload); err == nil {
result.CostUSD = payload.CostUSD
result.SessionID = payload.SessionID
for _, d := range payload.PermissionDenials {
result.PermissionDenials = append(result.PermissionDenials, PermissionDenial{
Tool: d.ToolName,
Input: d.Input,
})
}
return
}
}
// Fallback: cost might be at top level
if event.CostUSD > 0 {
result.CostUSD = event.CostUSD
}
if event.SessionID != "" {
result.SessionID = event.SessionID
}
}doctor.Run function · go · L38-L70 (33 LOC)internal/doctor/doctor.go
func Run(ctx context.Context, projectRoot, artifactsDir string, cfg *config.Config, st *state.State) error {
if st.Status != state.StatusFailed && st.Status != state.StatusInterrupted {
fmt.Println("No failed run to diagnose.")
return nil
}
if st.PhaseIndex >= len(cfg.Phases) {
return fmt.Errorf("phase index %d out of range (config has %d phases)", st.PhaseIndex, len(cfg.Phases))
}
phase := cfg.Phases[st.PhaseIndex]
phaseConfig := gatherPhaseConfig(phase)
log := gatherLog(artifactsDir, st.PhaseIndex)
prompt := gatherPrompt(artifactsDir, st.PhaseIndex, phase)
feedback := gatherFeedback(artifactsDir)
timing := gatherTiming(artifactsDir, phase.Name)
loops := gatherLoopCounts(artifactsDir)
diagText := buildPrompt(phaseConfig, log, prompt, feedback, timing, loops)
// Print header
fmt.Printf("\n%s%s══ Doctor: diagnosing phase %d/%d (%s) ══%s\n\n",
ux.Bold, ux.Cyan, st.PhaseIndex+1, len(cfg.Phases), phase.Name, ux.Reset)
if err := runClaude(ctx, diagText); err != doctor.buildPrompt function · go · L72-L93 (22 LOC)internal/doctor/doctor.go
func buildPrompt(phaseConfig, log, prompt, feedback, timing, loops string) string {
var promptSection, feedbackSection, timingSection string
if prompt != "" {
promptSection = fmt.Sprintf("\n## Agent Prompt\n%s\n", prompt)
}
if feedback != "" {
feedbackSection = fmt.Sprintf("\n## Feedback Files\n%s\n", feedback)
}
var extras []string
if timing != "" {
extras = append(extras, fmt.Sprintf("Timing: %s", timing))
}
if loops != "" {
extras = append(extras, fmt.Sprintf("Loop counts: %s", loops))
}
if len(extras) > 0 {
timingSection = fmt.Sprintf("\n## Execution Context\n%s\n", strings.Join(extras, "\n"))
}
return fmt.Sprintf(diagPrompt, phaseConfig, maxLogLines, log, promptSection, feedbackSection, timingSection)
}doctor.gatherPhaseConfig function · go · L95-L124 (30 LOC)internal/doctor/doctor.go
func gatherPhaseConfig(phase config.Phase) string {
var parts []string
parts = append(parts, fmt.Sprintf("Name: %s", phase.Name))
parts = append(parts, fmt.Sprintf("Type: %s", phase.Type))
if phase.Description != "" {
parts = append(parts, fmt.Sprintf("Description: %s", phase.Description))
}
if phase.Run != "" {
parts = append(parts, fmt.Sprintf("Run: %s", phase.Run))
}
if phase.Prompt != "" {
parts = append(parts, fmt.Sprintf("Prompt file: %s", phase.Prompt))
}
if phase.Model != "" {
parts = append(parts, fmt.Sprintf("Model: %s", phase.Model))
}
if phase.Timeout > 0 {
parts = append(parts, fmt.Sprintf("Timeout: %ds", phase.Timeout))
}
if len(phase.Outputs) > 0 {
parts = append(parts, fmt.Sprintf("Expected outputs: %s", strings.Join(phase.Outputs, ", ")))
}
if phase.Condition != "" {
parts = append(parts, fmt.Sprintf("Condition: %s", phase.Condition))
}
if phase.OnFail != nil {
parts = append(parts, fmt.Sprintf("On-fail: goto %s (max %d)", phase.OnFailRepobility — same analyzer, your code, free for public repos · /scan/
doctor.gatherLog function · go · L126-L138 (13 LOC)internal/doctor/doctor.go
func gatherLog(artifactsDir string, phaseIndex int) string {
path := state.LogPath(artifactsDir, phaseIndex)
data, err := os.ReadFile(path)
if err != nil {
return "(no log file found)"
}
lines := strings.Split(string(data), "\n")
if len(lines) > maxLogLines {
lines = lines[len(lines)-maxLogLines:]
return fmt.Sprintf("... (truncated to last %d lines)\n%s", maxLogLines, strings.Join(lines, "\n"))
}
return string(data)
}doctor.gatherPrompt function · go · L140-L150 (11 LOC)internal/doctor/doctor.go
func gatherPrompt(artifactsDir string, phaseIndex int, phase config.Phase) string {
if phase.Type != "agent" {
return ""
}
path := state.PromptPath(artifactsDir, phaseIndex)
data, err := os.ReadFile(path)
if err != nil {
return "(no rendered prompt found)"
}
return string(data)
}doctor.gatherFeedback function · go · L152-L170 (19 LOC)internal/doctor/doctor.go
func gatherFeedback(artifactsDir string) string {
dir := filepath.Join(artifactsDir, "feedback")
entries, err := os.ReadDir(dir)
if err != nil {
return ""
}
var parts []string
for _, e := range entries {
if e.IsDir() {
continue
}
data, err := os.ReadFile(filepath.Join(dir, e.Name()))
if err != nil {
continue
}
parts = append(parts, fmt.Sprintf("--- %s ---\n%s", e.Name(), string(data)))
}
return strings.Join(parts, "\n")
}page 1 / 2next ›