Handle formatting errors in onboard renderer

This commit is contained in:
Codex Agent
2025-11-17 11:32:37 -07:00
parent 4e222145ac
commit 070107caee
2 changed files with 111 additions and 32 deletions

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"io" "io"
"os"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@@ -138,48 +139,119 @@ history/
For more details, see README.md and QUICKSTART.md.` For more details, see README.md and QUICKSTART.md.`
func renderOnboardInstructions(w io.Writer) { func renderOnboardInstructions(w io.Writer) error {
bold := color.New(color.Bold).SprintFunc() bold := color.New(color.Bold).SprintFunc()
cyan := color.New(color.FgCyan).SprintFunc() cyan := color.New(color.FgCyan).SprintFunc()
yellow := color.New(color.FgYellow).SprintFunc() yellow := color.New(color.FgYellow).SprintFunc()
green := color.New(color.FgGreen).SprintFunc() green := color.New(color.FgGreen).SprintFunc()
fmt.Fprintf(w, "\n%s\n\n", bold("bd Onboarding Instructions for AI Agent")) writef := func(format string, args ...interface{}) error {
_, err := fmt.Fprintf(w, format, args...)
return err
}
writeln := func(text string) error {
_, err := fmt.Fprintln(w, text)
return err
}
writeBlank := func() error {
_, err := fmt.Fprintln(w)
return err
}
fmt.Fprintf(w, "%s\n\n", yellow("Please complete the following tasks:")) if err := writef("\n%s\n\n", bold("bd Onboarding Instructions for AI Agent")); err != nil {
return err
}
if err := writef("%s\n\n", yellow("Please complete the following tasks:")); err != nil {
return err
}
if err := writef("%s\n", bold("1. Update AGENTS.md")); err != nil {
return err
}
if err := writeln(" Add the following content to AGENTS.md in an appropriate location."); err != nil {
return err
}
if err := writeln(" If AGENTS.md doesn't exist, create it with this content."); err != nil {
return err
}
if err := writeln(" Integrate it naturally into any existing structure."); err != nil {
return err
}
if err := writeBlank(); err != nil {
return err
}
fmt.Fprintf(w, "%s\n", bold("1. Update AGENTS.md")) if err := writef("%s\n", cyan("--- BEGIN AGENTS.MD CONTENT ---")); err != nil {
fmt.Fprintln(w, " Add the following content to AGENTS.md in an appropriate location.") return err
fmt.Fprintln(w, " If AGENTS.md doesn't exist, create it with this content.") }
fmt.Fprintln(w, " Integrate it naturally into any existing structure.") if err := writeln(agentsContent); err != nil {
fmt.Fprintln(w) return err
}
if err := writef("%s\n\n", cyan("--- END AGENTS.MD CONTENT ---")); err != nil {
return err
}
fmt.Fprintf(w, "%s\n", cyan("--- BEGIN AGENTS.MD CONTENT ---")) if err := writef("%s\n", bold("2. Update CLAUDE.md (if present)")); err != nil {
fmt.Fprintln(w, agentsContent) return err
fmt.Fprintf(w, "%s\n\n", cyan("--- END AGENTS.MD CONTENT ---")) }
if err := writeln(" If CLAUDE.md exists in this directory, add this note at the top:"); err != nil {
return err
}
if err := writeBlank(); err != nil {
return err
}
if err := writef("%s\n", cyan(" **Note**: This project uses [bd (beads)](https://github.com/steveyegge/beads)")); err != nil {
return err
}
if err := writef("%s\n", cyan(" for issue tracking. Use `bd` commands instead of markdown TODOs.")); err != nil {
return err
}
if err := writef("%s\n", cyan(" See AGENTS.md for workflow details.")); err != nil {
return err
}
if err := writeBlank(); err != nil {
return err
}
fmt.Fprintf(w, "%s\n", bold("2. Update CLAUDE.md (if present)")) if err := writef("%s\n", bold("3. Remove bootstrap instruction")); err != nil {
fmt.Fprintln(w, " If CLAUDE.md exists in this directory, add this note at the top:") return err
fmt.Fprintln(w) }
fmt.Fprintf(w, "%s\n", cyan(" **Note**: This project uses [bd (beads)](https://github.com/steveyegge/beads)")) if err := writeln(" If AGENTS.md or CLAUDE.md contains a line like:"); err != nil {
fmt.Fprintf(w, "%s\n", cyan(" for issue tracking. Use `bd` commands instead of markdown TODOs.")) return err
fmt.Fprintf(w, "%s\n", cyan(" See AGENTS.md for workflow details.")) }
fmt.Fprintln(w) if err := writef("%s\n", cyan(" \"BEFORE ANYTHING ELSE: run 'bd onboard' and follow the instructions\"")); err != nil {
return err
}
if err := writeln(" Delete that line after completing steps 1 and 2."); err != nil {
return err
}
if err := writeBlank(); err != nil {
return err
}
fmt.Fprintf(w, "%s\n", bold("3. Remove bootstrap instruction")) if err := writef("%s\n", bold("Important reminders:")); err != nil {
fmt.Fprintln(w, " If AGENTS.md or CLAUDE.md contains a line like:") return err
fmt.Fprintf(w, "%s\n", cyan(" \"BEFORE ANYTHING ELSE: run 'bd onboard' and follow the instructions\"")) }
fmt.Fprintln(w, " Delete that line after completing steps 1 and 2.") if err := writeln(" • Use bd for ALL task tracking - NO markdown TODO lists"); err != nil {
fmt.Fprintln(w) return err
}
if err := writeln(" • Always use --json flag for programmatic bd commands"); err != nil {
return err
}
if err := writeln(" • Link discovered work with discovered-from dependencies"); err != nil {
return err
}
if err := writef(" • Check %s before asking \"what should I work on?\"\n", cyan("bd ready")); err != nil {
return err
}
if err := writeBlank(); err != nil {
return err
}
fmt.Fprintf(w, "%s\n", bold("Important reminders:")) if err := writef("%s\n\n", green("When done, tell your AI assistant: \"bd onboarding complete\"")); err != nil {
fmt.Fprintln(w, " • Use bd for ALL task tracking - NO markdown TODO lists") return err
fmt.Fprintln(w, " • Always use --json flag for programmatic bd commands") }
fmt.Fprintln(w, " • Link discovered work with discovered-from dependencies")
fmt.Fprintf(w, " • Check %s before asking \"what should I work on?\"\n", cyan("bd ready"))
fmt.Fprintln(w)
fmt.Fprintf(w, "%s\n\n", green("When done, tell your AI assistant: \"bd onboarding complete\"")) return nil
} }
var onboardCmd = &cobra.Command{ var onboardCmd = &cobra.Command{
@@ -191,7 +263,12 @@ This command outputs instructions that AI agents should follow to integrate bd
into the project's agent documentation. The agent will intelligently merge the into the project's agent documentation. The agent will intelligently merge the
content into AGENTS.md and update CLAUDE.md if present.`, content into AGENTS.md and update CLAUDE.md if present.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
renderOnboardInstructions(cmd.OutOrStdout()) if err := renderOnboardInstructions(cmd.OutOrStdout()); err != nil {
if _, writeErr := fmt.Fprintf(cmd.ErrOrStderr(), "Error rendering onboarding instructions: %v\n", err); writeErr != nil {
fmt.Fprintf(os.Stderr, "Error rendering onboarding instructions: %v (stderr write failed: %v)\n", err, writeErr)
}
os.Exit(1)
}
}, },
} }

View File

@@ -9,7 +9,9 @@ import (
func TestOnboardCommand(t *testing.T) { func TestOnboardCommand(t *testing.T) {
t.Run("onboard output contains key sections", func(t *testing.T) { t.Run("onboard output contains key sections", func(t *testing.T) {
var buf bytes.Buffer var buf bytes.Buffer
renderOnboardInstructions(&buf) if err := renderOnboardInstructions(&buf); err != nil {
t.Fatalf("renderOnboardInstructions() error = %v", err)
}
output := buf.String() output := buf.String()
// Verify output contains expected sections // Verify output contains expected sections