-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathtest_init.py
More file actions
250 lines (199 loc) · 8.45 KB
/
Copy pathtest_init.py
File metadata and controls
250 lines (199 loc) · 8.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
"""Tests for brigade init (CLI + install_selection behavior)."""
from __future__ import annotations
from pathlib import Path
import pytest
from brigade.install import install_selection
from brigade.selection import Selection
def _repo_sel() -> Selection:
return Selection(depth="repo", harnesses=["claude"], owner="claude", includes=[])
def _workspace_sel() -> Selection:
return Selection(depth="workspace", harnesses=["claude"], owner="claude", includes=[])
def _openclaw_sel() -> Selection:
return Selection(
depth="workspace",
harnesses=["claude", "openclaw"],
owner="openclaw",
includes=[],
)
def _hermes_sel() -> Selection:
return Selection(
depth="workspace",
harnesses=["claude", "hermes"],
owner="hermes",
includes=[],
)
def _generic_sel() -> Selection:
return Selection(depth="workspace", harnesses=[], owner="this-repo", includes=[])
def _publisher_sel() -> Selection:
return Selection(
depth="repo",
harnesses=["claude"],
owner="claude",
includes=["publisher"],
)
def test_repo_install_lays_down_expected_files(tmp_target: Path):
rc = install_selection(tmp_target, _repo_sel())
assert rc == 0
assert (tmp_target / "AGENTS.md").is_file()
assert (tmp_target / "CLAUDE.md").is_file()
assert (tmp_target / ".claude" / "memory-handoffs" / "TEMPLATE.md").is_file()
assert (tmp_target / "hooks" / "pre-push").is_file()
# pre-push must be executable
mode = (tmp_target / "hooks" / "pre-push").stat().st_mode & 0o777
assert mode & 0o100, f"hooks/pre-push not executable: {oct(mode)}"
def test_workspace_install_includes_memory_cards(tmp_target: Path):
rc = install_selection(tmp_target, _workspace_sel())
assert rc == 0
for fname in (
"AGENTS.md",
"CLAUDE.md",
"SOUL.md",
"USER.md",
"TOOLS.md",
"MEMORY.md",
"IDENTITY.md",
"HEARTBEAT.md",
"SAFETY_RULES.md",
"INSTALL_FOR_AGENTS.md",
):
assert (tmp_target / fname).is_file(), f"missing {fname}"
for card in (
"memory-architecture.md",
"handoff-flow.md",
"content-safety.md",
"memory-scanner.md",
"memory-care-staleness.md",
"multi-workspace-handoff-admin.md",
"tokenjuice-output-compaction.md",
"chat-surface-crawlers.md",
"pipeline-standups.md",
"obsidian-notes.md",
"backup-restic.md",
):
assert (tmp_target / "memory" / "cards" / card).is_file(), f"missing card {card}"
assert (tmp_target / "memory" / "handoff-inbox").is_dir()
assert (tmp_target / ".claude" / "memory-handoffs" / "processed").is_dir()
assert (tmp_target / ".brigade" / "memory-care.example.json").is_file()
# skill + script land at the right paths, executable bit on the script
assert (tmp_target / "skills" / "note" / "SKILL.md").is_file()
backup = tmp_target / "scripts" / "backup-restic.sh"
assert backup.is_file()
assert backup.stat().st_mode & 0o111, "backup-restic.sh should be executable"
def test_openclaw_install_extends_workspace(tmp_target: Path):
rc = install_selection(tmp_target, _openclaw_sel())
assert rc == 0
# workspace files present
assert (tmp_target / "MEMORY.md").is_file()
# openclaw fragments present
fragments_dir = tmp_target / ".brigade" / "openclaw"
assert (fragments_dir / "model-aliases.openclaw.json").is_file()
assert (fragments_dir / "ollama-memory-search.openclaw.json").is_file()
assert (fragments_dir / "acp-escalation.openclaw.json").is_file()
def test_hermes_install_writes_experimental_fragments(tmp_target: Path):
rc = install_selection(tmp_target, _hermes_sel())
assert rc == 0
fragments_dir = tmp_target / ".brigade" / "hermes"
assert (fragments_dir / "workspace.harness.json").is_file()
assert (fragments_dir / "memory-handoff.harness.json").is_file()
assert (fragments_dir / "model-lanes.harness.json").is_file()
def test_generic_install_writes_baseline_workspace(tmp_target: Path):
"""`--harnesses none` still produces a workspace baseline with AGENTS.md + memory folders."""
rc = install_selection(tmp_target, _generic_sel())
assert rc == 0
assert (tmp_target / "AGENTS.md").is_file()
assert (tmp_target / "MEMORY.md").is_file()
# No harness writer => no .claude/.codex inbox.
assert not (tmp_target / ".claude" / "memory-handoffs").exists()
assert not (tmp_target / ".codex" / "memory-handoffs").exists()
def test_publisher_include_writes_policies(tmp_target: Path):
rc = install_selection(tmp_target, _publisher_sel())
assert rc == 0
assert (tmp_target / "hooks" / "pre-push").is_file()
assert (tmp_target / ".brigade" / "policies" / "public-repo.json").is_file()
assert (tmp_target / ".brigade" / "policies" / "public-content.json").is_file()
def test_dry_run_creates_no_files_or_dirs(tmp_target: Path):
rc = install_selection(tmp_target, _workspace_sel(), dry_run=True)
assert rc == 0
# Dry-run must not even materialize the target directory.
assert not tmp_target.exists()
def test_install_refuses_home_directory(tmp_path: Path, monkeypatch):
monkeypatch.setattr(Path, "home", lambda: tmp_path)
rc = install_selection(tmp_path, _repo_sel())
assert rc == 5
assert not (tmp_path / "AGENTS.md").exists()
def test_install_allow_home_overrides(tmp_path: Path, monkeypatch):
monkeypatch.setattr(Path, "home", lambda: tmp_path)
rc = install_selection(tmp_path, _repo_sel(), allow_home=True)
assert rc == 0
assert (tmp_path / "AGENTS.md").exists()
def test_install_refuses_overwrite_without_force(tmp_target: Path):
tmp_target.mkdir()
(tmp_target / "AGENTS.md").write_text("# pre-existing\n")
rc = install_selection(tmp_target, _repo_sel())
assert rc == 3
# original content untouched
assert (tmp_target / "AGENTS.md").read_text() == "# pre-existing\n"
def test_force_overwrites_existing(tmp_target: Path):
tmp_target.mkdir()
(tmp_target / "AGENTS.md").write_text("# pre-existing\n")
rc = install_selection(tmp_target, _repo_sel(), force=True)
assert rc == 0
text = (tmp_target / "AGENTS.md").read_text()
assert "# pre-existing" not in text
assert "AGENTS.md" in text or "Memory Owner" in text
def test_memory_owner_placeholder_renders_per_selection(tmp_target: Path):
install_selection(tmp_target, _openclaw_sel())
agents = (tmp_target / "AGENTS.md").read_text()
assert "OpenClaw" in agents
assert "{{" not in agents and "}}" not in agents
def test_owner_override_renders_in_bootstrap(tmp_target: Path):
sel = Selection(
depth="repo",
harnesses=["claude", "hermes"],
owner="hermes",
includes=[],
)
install_selection(tmp_target, sel)
agents = (tmp_target / "AGENTS.md").read_text()
assert "Hermes" in agents
def test_cli_parses_depth_harnesses(monkeypatch, tmp_path):
from brigade.cli import _build_parser
parser = _build_parser()
ns = parser.parse_args([
"init",
"--target", str(tmp_path),
"--depth", "workspace",
"--harnesses", "claude,codex,openclaw",
"--owner", "openclaw",
"--include", "publisher",
])
assert ns.depth == "workspace"
assert ns.harnesses == "claude,codex,openclaw"
assert ns.owner == "openclaw"
assert ns.includes == ["publisher"]
def test_cli_rejects_unknown_harness(tmp_path):
from brigade.cli import main
rc = main([
"init", "--target", str(tmp_path),
"--harnesses", "claude,weird",
])
assert rc != 0
def test_cli_invokes_prompt_when_no_selection_flags(monkeypatch, tmp_path):
"""init without any selection flags should call prompt_for_selection."""
called = {}
from brigade import cli
from brigade.selection import Selection
def fake_prompt():
called["yes"] = True
return Selection(depth="repo", harnesses=["claude"], owner="claude", includes=[])
monkeypatch.setattr(cli, "prompt_for_selection", fake_prompt)
rc = cli.main(["init", "--target", str(tmp_path)])
assert rc == 0
assert called.get("yes") is True
def test_cli_skips_prompt_when_depth_given(monkeypatch, tmp_path):
from brigade import cli
def fail():
raise AssertionError("prompt should not be called")
monkeypatch.setattr(cli, "prompt_for_selection", fail)
rc = cli.main(["init", "--target", str(tmp_path), "--depth", "repo", "--harnesses", "claude"])
assert rc == 0