Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ mise run test:e2e:canary TestFoo # Run a specific test
- **If a canary test fails, the bug is in the CLI or test infrastructure**, not in an agent
- Located in `e2e/vogon/` (binary) and `cmd/entire/cli/agent/vogon/` (Agent interface)
- The binary parses prompts via regex, creates/modifies/deletes files, and fires lifecycle hooks
- **IMPORTANT: When changing E2E test prompt wording**, the Vogon binary (`e2e/vogon/main.go`) parses prompts with hardcoded regexes. New phrasing may not match existing patterns — always run `mise run test:e2e:canary` after changing prompt text and fix Vogon's parsing if tests fail.

### Running E2E Tests (Only When Explicitly Requested)

Expand Down
6 changes: 5 additions & 1 deletion e2e/tests/edge_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ func TestDirtyWorkingTree(t *testing.T) {
func TestRapidSequentialCommits(t *testing.T) {
testutil.ForEachAgent(t, 4*time.Minute, func(t *testing.T, s *testutil.RepoState, ctx context.Context) {
_, err := s.RunPrompt(t, ctx,
"create three separate markdown files: docs/red.md about red, docs/blue.md about blue, docs/green.md about green. Commit each file separately right after creating it — three separate git commits. Do not ask for confirmation, just make the changes.",
"Do these steps in exact order: "+
"(1) Create docs/red.md with a paragraph about the colour red. Run: git add docs/red.md && git commit -m 'Add red.md'. "+
"(2) Create docs/blue.md with a paragraph about the colour blue. Run: git add docs/blue.md && git commit -m 'Add blue.md'. "+
"(3) Create docs/green.md with a paragraph about the colour green. Run: git add docs/green.md && git commit -m 'Add green.md'. "+
"Do not ask for confirmation, just execute each step.",
agents.WithPromptTimeout(120*time.Second))
if err != nil {
t.Fatalf("agent failed: %v", err)
Expand Down
39 changes: 33 additions & 6 deletions e2e/vogon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,31 +290,58 @@ func parseNumberedSteps(prompt string) []action {

var actions []action
for _, step := range steps {
// Explicit git command: "Run: git add ... && git commit ..."
if explicitGitRe.MatchString(step) {
actions = append(actions, action{kind: "commit"})
continue
}
hasExplicitGit := explicitGitRe.MatchString(step)

// Create file with optional inline content
// Create file with optional inline content.
// Try the full "create ... file ... <path>" regex first, then fall back
// to "Create <path>" (any file path after a Create verb).
if m := createFileRe.FindStringSubmatch(step); m != nil {
content := fmt.Sprintf("# %s\n\nGenerated content.\n", m[1])
if ic := inlineContentRe.FindStringSubmatch(step); ic != nil {
content = ic[1] + "\n"
}
actions = append(actions, action{kind: "create", path: m[1], content: content})
if hasExplicitGit {
actions = append(actions, action{kind: "commit"})
}
continue
}
if strings.HasPrefix(strings.ToLower(strings.TrimSpace(step)), "create") {
if m := anyFileRe.FindStringSubmatch(step); m != nil {
topic := extractTopic(step)
content := fmt.Sprintf("# %s\n\nA paragraph about %s.\n", topic, topic)
if ic := inlineContentRe.FindStringSubmatch(step); ic != nil {
content = ic[1] + "\n"
}
actions = append(actions, action{kind: "create", path: m[1], content: content})
if hasExplicitGit {
actions = append(actions, action{kind: "commit"})
}
continue
}
}

// Modify file
if m := modifyFileRe.FindStringSubmatch(step); m != nil {
actions = append(actions, action{kind: "modify", path: m[1], content: "// Modified by vogon agent\n"})
if hasExplicitGit {
actions = append(actions, action{kind: "commit"})
}
continue
}

// Delete file
if m := deleteFileRe.FindStringSubmatch(step); m != nil {
actions = append(actions, action{kind: "delete", path: m[1]})
if hasExplicitGit {
actions = append(actions, action{kind: "commit"})
}
continue
}

// Explicit git command without a file operation in this step
if hasExplicitGit {
actions = append(actions, action{kind: "commit"})
continue
}

Expand Down