v0.11.2 619aabb

fast_mode_test.go RawHistoryFolder

1package subagents
2
3import (
4	"context"
5	"strings"
6	"testing"
7)
8
9func TestSupervisorFastModePropagatesToChild(t *testing.T) {
10	root := t.TempDir()
11	f := New(Config{
12		Root:     root,
13		RepoRoot: root,
14		FastMode: true,
15		NewRunner: func(a *Agent) Runner {
16			return RunnerFunc(func(ctx context.Context, _ Sink) error {
17				<-ctx.Done()
18				return ctx.Err()
19			})
20		},
21	})
22
23	a, err := f.SpawnReq(context.Background(), SpawnRequest{Task: "x"})
24	if err != nil {
25		t.Fatalf("spawn: %v", err)
26	}
27	cleanedUp := false
28	t.Cleanup(func() {
29		if cleanedUp {
30			return
31		}
32		if err := f.Stop(a.ID); err != nil {
33			t.Errorf("cleanup stop: %v", err)
34		}
35		a.Wait()
36	})
37	if !a.FastMode {
38		t.Fatal("spawned agent FastMode = false, want true")
39	}
40	args := defaultChildArgs("/zut", a, "/session", "/inbox")
41	if !containsArg(args, "--fast-mode") {
42		t.Fatalf("child args = %v, want --fast-mode", args)
43	}
44
45	if err := f.Stop(a.ID); err != nil {
46		t.Fatalf("stop: %v", err)
47	}
48	a.Wait()
49	cleanedUp = true
50
51	g := New(Config{Root: root, RepoRoot: root})
52	if loaded, errs := g.Reload(); loaded != 1 || len(errs) != 0 {
53		t.Fatalf("reload loaded=%d errs=%v", loaded, errs)
54	}
55	reloaded := g.Get(a.ID)
56	if reloaded == nil || !reloaded.FastMode {
57		t.Fatalf("reloaded FastMode = %v, want true", reloaded != nil && reloaded.FastMode)
58	}
59}
60
61func TestSpawnRequestFastModeProfileOverridesHostSetting(t *testing.T) {
62	falseValue, trueValue := false, true
63	cases := []struct {
64		name             string
65		hostFast         bool
66		profileFast      *bool
67		want             bool
68		wantHostOverride bool
69	}{
70		{name: "unset inherits enabled host", hostFast: true, want: true},
71		{name: "unset inherits disabled host", hostFast: false, want: false},
72		{name: "false disables enabled host", hostFast: true, profileFast: &falseValue, want: false},
73		{name: "true enables disabled host", hostFast: false, profileFast: &trueValue, want: true, wantHostOverride: true},
74		{name: "true preserves enabled host", hostFast: true, profileFast: &trueValue, want: true},
75	}
76	for _, tc := range cases {
77		t.Run(tc.name, func(t *testing.T) {
78			root := t.TempDir()
79			f := New(Config{
80				Root:     root,
81				RepoRoot: root,
82				FastMode: tc.hostFast,
83				NewRunner: func(*Agent) Runner {
84					return RunnerFunc(func(context.Context, Sink) error { return nil })
85				},
86			})
87			a, err := f.SpawnReq(context.Background(), SpawnRequest{Task: "x", FastMode: tc.profileFast})
88			if err != nil {
89				t.Fatalf("spawn: %v", err)
90			}
91			a.Wait()
92			if a.FastMode != tc.want {
93				t.Fatalf("FastMode = %v, want %v", a.FastMode, tc.want)
94			}
95			if a.FastModeOverridesHost() != tc.wantHostOverride {
96				t.Fatalf("FastModeOverridesHost() = %v, want %v", a.FastModeOverridesHost(), tc.wantHostOverride)
97			}
98			args := defaultChildArgs("/zut", a, "/session", "/inbox")
99			wantFlag := "--no-fast-mode"
100			if tc.want {
101				wantFlag = "--fast-mode"
102			}
103			if !containsArg(args, wantFlag) {
104				t.Fatalf("child args = %v, want %s", args, wantFlag)
105			}
106		})
107	}
108}
109
110func TestSupervisorReloadPreservesExplicitFastModeOff(t *testing.T) {
111	root := t.TempDir()
112	newSupervisor := func(fastMode bool) *Supervisor {
113		return New(Config{
114			Root:     root,
115			RepoRoot: root,
116			FastMode: fastMode,
117			NewRunner: func(a *Agent) Runner {
118				return RunnerFunc(func(ctx context.Context, _ Sink) error {
119					<-ctx.Done()
120					return ctx.Err()
121				})
122			},
123		})
124	}
125
126	f := newSupervisor(false)
127	a, err := f.SpawnReq(context.Background(), SpawnRequest{Task: "x"})
128	if err != nil {
129		t.Fatalf("spawn: %v", err)
130	}
131	if a.FastMode {
132		t.Fatal("spawned agent FastMode = true, want false")
133	}
134	if err := f.Stop(a.ID); err != nil {
135		t.Fatalf("stop: %v", err)
136	}
137	a.Wait()
138
139	g := newSupervisor(true)
140	if loaded, errs := g.Reload(); loaded != 1 || len(errs) != 0 {
141		t.Fatalf("reload loaded=%d errs=%v", loaded, errs)
142	}
143	if reloaded := g.Get(a.ID); reloaded == nil || reloaded.FastMode {
144		t.Fatalf("reloaded FastMode = %v, want false", reloaded != nil && reloaded.FastMode)
145	}
146}
147
148func TestSubagentWorkerArgsOmitFastModeWhenUnset(t *testing.T) {
149	args := subagentWorkerArgs(subagentWorkerArgsOpts{Exe: "/zut", Dir: "/wt", SessionPath: "/s", InboxPath: "/i"})
150	if strings.Contains(strings.Join(args, " "), "--fast-mode") || strings.Contains(strings.Join(args, " "), "--no-fast-mode") {
151		t.Fatalf("child args = %v, want fast mode omitted when unset", args)
152	}
153}
154
155func TestSubagentWorkerArgsExplicitlyDisablesFastMode(t *testing.T) {
156	args := subagentWorkerArgs(subagentWorkerArgsOpts{
157		Exe:         "/zut",
158		Dir:         "/wt",
159		SessionPath: "/s",
160		InboxPath:   "/i",
161		FastModeSet: true,
162	})
163	if !containsArg(args, "--no-fast-mode") {
164		t.Fatalf("child args = %v, want --no-fast-mode", args)
165	}
166	if containsArg(args, "--fast-mode") {
167		t.Fatalf("child args = %v, want no positive fast-mode flag", args)
168	}
169}
170
171func TestDefaultChildArgsExplicitlyDisablesFastMode(t *testing.T) {
172	args := defaultChildArgs("/zut", &Agent{Dir: "/wt"}, "/s", "/i")
173	if !containsArg(args, "--no-fast-mode") {
174		t.Fatalf("child args = %v, want --no-fast-mode", args)
175	}
176}
177
178func containsArg(args []string, want string) bool {
179	for _, arg := range args {
180		if arg == want {
181			return true
182		}
183	}
184	return false
185}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 477

↑↓ moveenter openesc close