__init__.py python
454 lines 13.7 KB
Raw
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 9 hours ago
1 """Fixture builders for multi-repo workspace lanes tests (§MR.9–§MR.10)."""
2
3 from __future__ import annotations
4
5 from pathlib import Path
6
7 import yaml
8
9 from tools.workspace.next_extract import tip_hash_hex
10
11
12 def _member_config(
13 *,
14 name: str,
15 regime: str,
16 handover: str,
17 roadmap: str,
18 handover_title: str,
19 roadmap_title: str,
20 constellation_id: str | None = None,
21 product_order_root: str | None = None,
22 manifest: str | None = None,
23 ) -> dict:
24 if regime == "muse-only":
25 vcs = {
26 "regime": "muse-only",
27 "canonical": "muse",
28 "git": {
29 "remote": "origin",
30 "main_branch": "main",
31 "mirror_branch": None,
32 "feature_branch_pattern": "feat/{slug}",
33 },
34 "muse": {"staging_remote": None, "main_branch": "main"},
35 }
36 elif regime == "muse+git-mirror":
37 vcs = {
38 "regime": "muse+git-mirror",
39 "canonical": "muse",
40 "git": {
41 "remote": "origin",
42 "main_branch": "main",
43 "mirror_branch": "muse-mirror",
44 "feature_branch_pattern": "feat/{slug}",
45 },
46 "muse": {"staging_remote": "staging", "main_branch": "main"},
47 }
48 else:
49 vcs = {
50 "regime": "git-only",
51 "canonical": "git",
52 "git": {
53 "remote": "origin",
54 "main_branch": "main",
55 "mirror_branch": None,
56 "feature_branch_pattern": "feat/{slug}",
57 },
58 "muse": {"staging_remote": None, "main_branch": None},
59 }
60
61 cfg: dict = {
62 "overseer_config_version": 1,
63 "repo": {"name": name, "root_relative_docs": "docs"},
64 "vcs": vcs,
65 "docs": {
66 "handover": handover,
67 "roadmap": roadmap,
68 "coordination": None,
69 "standing_decisions": roadmap,
70 "handover_title": handover_title,
71 "roadmap_title": roadmap_title,
72 },
73 "thresholds": {"realign_max_commits": 50, "drift_warn_only": True},
74 "freeze_contract": {
75 "enabled": True,
76 "reviewer": {
77 "mode": "agent",
78 "model": "thinking-high",
79 "provider": "local",
80 "fallback": "human",
81 },
82 "human_escalation": ["security"],
83 },
84 }
85 if constellation_id is not None:
86 ws: dict = {"constellation_id": constellation_id}
87 if product_order_root is not None:
88 ws["product_order_root"] = product_order_root
89 if manifest is not None:
90 ws["manifest"] = manifest
91 cfg["workspace"] = ws
92 return cfg
93
94
95 def primary_fence(
96 *,
97 step: str,
98 model: str,
99 repo: str,
100 branch: str = "feat/test",
101 authority: str = "authoritative",
102 ) -> str:
103 return (
104 f"Phase {step} — test.\n"
105 f"\n"
106 f"Model: {model}\n"
107 f"Repo: {repo}\n"
108 f"Branch: {branch}\n"
109 f"Step: {step}\n"
110 f"Authority: {authority}\n"
111 )
112
113
114 def write_primary_handover(
115 path: Path,
116 *,
117 title: str,
118 step: str,
119 model: str,
120 repo: str,
121 lane: str = "product",
122 extra_blocks: str = "",
123 ) -> str:
124 """Write product_order PRIMARY handover; return tip_hash of paste fence."""
125 fence = primary_fence(step=step, model=model, repo=repo)
126 digest = tip_hash_hex(fence)
127 text = (
128 f"# {title}\n"
129 f"\n"
130 f"<!-- overseer:next role=primary lane={lane} status=live -->\n"
131 f"## NEXT SESSION — {step} (PRIMARY)\n"
132 f"\n"
133 f"**Model:** {model}\n"
134 f"\n"
135 f"### THE ONE NEXT STEP — **Model: {model}**\n"
136 f"\n"
137 f"| | |\n"
138 f"| --- | --- |\n"
139 f"| **ID** | **{step}** |\n"
140 f"| **Branch** | `feat/test` |\n"
141 f"| **Repo** | **{repo}** |\n"
142 f"\n"
143 f"### Paste-ready prompt — {step}\n"
144 f"\n"
145 f"```\n"
146 f"{fence}"
147 f"```\n"
148 f"\n"
149 f"{extra_blocks}\n"
150 )
151 path.parent.mkdir(parents=True, exist_ok=True)
152 path.write_text(text, encoding="utf-8")
153 return digest
154
155
156 def write_relay_handover(
157 path: Path,
158 *,
159 title: str,
160 step: str,
161 model: str,
162 product_order: str,
163 tip_hash: str,
164 mode: str = "relay",
165 ownership_primary: bool = False,
166 ownership_step: str = "SEC-1",
167 stale: bool = False,
168 ) -> None:
169 """Write ownership/enrichment board with RELAY or PRODUCT RELAY tip."""
170 tip_step = "STALE-OLD" if stale else step
171 tip_model = "Thinking" if stale else model
172 tip_digest = "0" * 64 if stale else tip_hash
173 redirect = (
174 f"Model: {tip_model}\n"
175 f"Repo: open product_order {product_order}\n"
176 f"Branch: unknown\n"
177 f"Step: {tip_step}\n"
178 f"Authority: relay\n"
179 f"Open product_order handover for authoritative paste.\n"
180 )
181 if ownership_primary and mode == "product_relay":
182 text = (
183 f"# {title}\n"
184 f"\n"
185 f"<!-- overseer:next role=primary lane=product status=live -->\n"
186 f"## NEXT SESSION — {ownership_step} ownership work (PRIMARY)\n"
187 f"\n"
188 f"**Model:** Auto\n"
189 f"\n"
190 f"### Paste-ready prompt — {ownership_step}\n"
191 f"\n"
192 f"```\n"
193 f"Model: Auto\n"
194 f"Repo: ownership\n"
195 f"Branch: feat/own\n"
196 f"Step: {ownership_step}\n"
197 f"Authority: authoritative\n"
198 f"```\n"
199 f"\n"
200 f"<!-- overseer:next role=product_relay lane=product status=live "
201 f"product_order={product_order} tip_hash=sha256:{tip_digest} -->\n"
202 f"## PRODUCT RELAY — {product_order} {tip_step} {tip_model}\n"
203 f"\n"
204 f"```\n"
205 f"{redirect}"
206 f"```\n"
207 )
208 elif mode == "relay":
209 text = (
210 f"# {title}\n"
211 f"\n"
212 f"<!-- overseer:next role=relay lane=product status=live "
213 f"product_order={product_order} tip_hash=sha256:{tip_digest} -->\n"
214 f"## NEXT SESSION — Product tip (RELAY → {product_order} {tip_step} {tip_model})\n"
215 f"\n"
216 f"**Model:** {tip_model}\n"
217 f"\n"
218 f"### Paste-ready prompt — relay\n"
219 f"\n"
220 f"```\n"
221 f"{redirect}"
222 f"```\n"
223 )
224 else:
225 raise ValueError(f"unsupported mode {mode}")
226 path.parent.mkdir(parents=True, exist_ok=True)
227 path.write_text(text, encoding="utf-8")
228
229
230 def build_two_repo_constellation(
231 root: Path,
232 *,
233 stale_relay: bool = False,
234 bare_names_on_relay: bool = False,
235 with_brain: bool = False,
236 with_musehub: bool = False,
237 with_lane_tip: bool = False,
238 ownership_product_relay: bool = False,
239 missing_product_relay: bool = False,
240 constellation_id: str = "fixture-stack",
241 ) -> dict:
242 """Create product_order + ownership (+ optional) fixture constellation.
243
244 Returns paths dict for tests.
245 """
246 scooling = root / "scooling"
247 knowtation = root / "knowtation"
248 for path in (scooling, knowtation):
249 (path / ".overseer").mkdir(parents=True)
250 (path / "docs").mkdir(parents=True)
251
252 scooling_ho = "SCOOLING-OVERSEER-HANDOVER.md"
253 scooling_rm = "SCOOLING-ROADMAP.md"
254 if bare_names_on_relay:
255 know_ho = "OVERSEER-HANDOVER.md"
256 know_rm = "ROADMAP.md"
257 know_title = "Overseer Handover"
258 else:
259 know_ho = "KNOWTATION-OVERSEER-HANDOVER.md"
260 know_rm = "KNOWTATION-ROADMAP.md"
261 know_title = "Knowtation Overseer Handover"
262
263 tip_hash = write_primary_handover(
264 scooling / "docs" / scooling_ho,
265 title="Scooling Overseer Handover",
266 step="L-SEAMb",
267 model="Auto",
268 repo=str(scooling),
269 )
270 lane_extra = ""
271 if with_lane_tip:
272 lane_extra = (
273 "<!-- overseer:next role=lane_tip lane=security status=live -->\n"
274 "## LANE TIP — Security harden (LANE: security)\n"
275 "\n"
276 "### Paste-ready prompt — security\n"
277 "\n"
278 "```\n"
279 "Model: Thinking\n"
280 "Repo: scooling\n"
281 "Branch: feat/sec\n"
282 "Step: SEC-LANE\n"
283 "Authority: lane_tip\n"
284 "```\n"
285 )
286 # Append lane tip to scooling handover
287 path = scooling / "docs" / scooling_ho
288 path.write_text(path.read_text(encoding="utf-8") + "\n" + lane_extra, encoding="utf-8")
289
290 (scooling / "docs" / scooling_rm).write_text("# Scooling Roadmap\n", encoding="utf-8")
291 (knowtation / "docs" / know_rm).write_text("# Knowtation Roadmap\n", encoding="utf-8")
292
293 if missing_product_relay:
294 # Ownership PRIMARY only — no product tip
295 (knowtation / "docs" / know_ho).write_text(
296 (
297 "# Knowtation\n"
298 "\n"
299 "<!-- overseer:next role=primary lane=product status=live -->\n"
300 "## NEXT SESSION — SEC-9 ownership (PRIMARY)\n"
301 "\n"
302 "### Paste-ready prompt\n"
303 "\n"
304 "```\n"
305 "Model: Auto\n"
306 "Repo: knowtation\n"
307 "Branch: feat/sec\n"
308 "Step: SEC-9\n"
309 "Authority: authoritative\n"
310 "```\n"
311 ),
312 encoding="utf-8",
313 )
314 elif ownership_product_relay:
315 write_relay_handover(
316 knowtation / "docs" / know_ho,
317 title=know_title,
318 step="L-SEAMb",
319 model="Auto",
320 product_order="scooling",
321 tip_hash=tip_hash,
322 mode="product_relay",
323 ownership_primary=True,
324 stale=stale_relay,
325 )
326 else:
327 write_relay_handover(
328 knowtation / "docs" / know_ho,
329 title=know_title,
330 step="L-SEAMb",
331 model="Auto",
332 product_order="scooling",
333 tip_hash=tip_hash,
334 mode="relay",
335 stale=stale_relay,
336 )
337
338 members = [
339 {
340 "id": "scooling",
341 "role": "product_order",
342 "root": str(scooling),
343 "regime": "git-only",
344 "required": True,
345 "relay": False,
346 },
347 {
348 "id": "knowtation",
349 "role": "ownership",
350 "root": str(knowtation),
351 "regime": "git-only",
352 "required": True,
353 "relay": True,
354 },
355 ]
356 lanes = [
357 {"id": "product", "primary": True, "owner_member": "scooling"},
358 {"id": "security", "primary": False, "owner_member": "knowtation"},
359 ]
360
361 musehub = None
362 if with_musehub:
363 musehub = root / "musehub"
364 (musehub / ".overseer").mkdir(parents=True)
365 (musehub / "docs").mkdir(parents=True)
366 (musehub / "docs" / "MUSEHUB-OVERSEER-HANDOVER.md").write_text(
367 "# MuseHub\n", encoding="utf-8"
368 )
369 (musehub / "docs" / "MUSEHUB-ROADMAP.md").write_text("# MuseHub Roadmap\n", encoding="utf-8")
370 mh_cfg = _member_config(
371 name="musehub",
372 regime="muse-only",
373 handover="MUSEHUB-OVERSEER-HANDOVER.md",
374 roadmap="MUSEHUB-ROADMAP.md",
375 handover_title="MuseHub Overseer Handover",
376 roadmap_title="MuseHub Roadmap",
377 constellation_id=constellation_id,
378 product_order_root=str(scooling),
379 )
380 (musehub / ".overseer" / "config.yaml").write_text(
381 yaml.safe_dump(mh_cfg, sort_keys=False), encoding="utf-8"
382 )
383 members.append(
384 {
385 "id": "musehub",
386 "role": "enrichment",
387 "root": str(musehub),
388 "regime": "muse-only",
389 "required": False,
390 "relay": False,
391 }
392 )
393
394 if with_brain:
395 members.append(
396 {
397 "id": "brain",
398 "role": "edge",
399 "root": "${BRAIN_ROOT}",
400 "regime": None,
401 "required": False,
402 "relay": False,
403 }
404 )
405
406 manifest = {
407 "overseer_workspace_version": 1,
408 "id": constellation_id,
409 "product_order_member": "scooling",
410 "strict_markers": True,
411 "strict_board_names": True,
412 "members": members,
413 "lanes": lanes,
414 }
415 manifest_path = scooling / ".overseer" / "workspace.yaml"
416 manifest_path.write_text(yaml.safe_dump(manifest, sort_keys=False), encoding="utf-8")
417
418 scooling_cfg = _member_config(
419 name="scooling",
420 regime="git-only",
421 handover=scooling_ho,
422 roadmap=scooling_rm,
423 handover_title="Scooling Overseer Handover",
424 roadmap_title="Scooling Roadmap",
425 constellation_id=constellation_id,
426 manifest=str(manifest_path),
427 )
428 know_cfg = _member_config(
429 name="knowtation",
430 regime="git-only",
431 handover=know_ho,
432 roadmap=know_rm,
433 handover_title=know_title,
434 roadmap_title="Knowtation Roadmap",
435 constellation_id=constellation_id,
436 product_order_root=str(scooling),
437 )
438 (scooling / ".overseer" / "config.yaml").write_text(
439 yaml.safe_dump(scooling_cfg, sort_keys=False), encoding="utf-8"
440 )
441 (knowtation / ".overseer" / "config.yaml").write_text(
442 yaml.safe_dump(know_cfg, sort_keys=False), encoding="utf-8"
443 )
444
445 return {
446 "scooling": scooling,
447 "knowtation": knowtation,
448 "musehub": musehub,
449 "manifest": manifest_path,
450 "tip_hash": tip_hash,
451 "constellation_id": constellation_id,
452 "scooling_handover": scooling / "docs" / scooling_ho,
453 "knowtation_handover": knowtation / "docs" / know_ho,
454 }
File History 1 commit
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 9 hours ago