|
|
@@ -0,0 +1,142 @@
|
|
|
+from harness import * # noqa: F401,F403 — the shared wire helpers
|
|
|
+
|
|
|
+
|
|
|
+"""Goal 8 task 6 (web side): the register handshake stores the daemon's
|
|
|
+reported `workspace_root`, and assignment project paths are addressed on
|
|
|
+the ASKING saddle's filesystem — the saddle row's root first, then the
|
|
|
+SADDLE_PROJECTS_ROOT environment override, then the historical
|
|
|
+"/workspace" default. The web app needs NO access to saddle workspaces:
|
|
|
+paths are advisory and multi-saddle goals coordinate through origin."""
|
|
|
+
|
|
|
+
|
|
|
+def run(ctx):
|
|
|
+ auth, fake, fake_id, fake_token = ctx.auth, ctx.fake, ctx.fake_id, ctx.fake_token
|
|
|
+
|
|
|
+ print("== origin decoupling: the handshake stores the reported root ==")
|
|
|
+ # The primary fake reports /workspace by default; the row carries it
|
|
|
+ # once registration completes (the stacks bundle's demo project is
|
|
|
+ # project 1 in every shard).
|
|
|
+ def saddle_row(name):
|
|
|
+ return next((s for s in slot_public(auth, "/saddles", "saddles")["saddles"]
|
|
|
+ if s["name"] == name), None)
|
|
|
+
|
|
|
+ primary = saddle_row("fake-saddle")
|
|
|
+ check(primary is not None, "the primary fake saddle is registered")
|
|
|
+ if primary is not None:
|
|
|
+ check(primary.get("workspace_root") == "/workspace",
|
|
|
+ "the register handshake stores the daemon-reported workspace_root (%r)"
|
|
|
+ % primary.get("workspace_root"))
|
|
|
+
|
|
|
+ print("== origin decoupling: assignment paths follow the ASKING saddle ==")
|
|
|
+ # A second saddle on its own volume: its daemon reports a DIFFERENT
|
|
|
+ # workspace root — the fleet's separate-mount deployment shape.
|
|
|
+ other = FakeSaddle()
|
|
|
+ other.workspace_root = "/volumes/saddle-b"
|
|
|
+ other.serve(port=free_port())
|
|
|
+ saddles_state = slot_public(auth, "/saddles", "saddles")
|
|
|
+ act(auth, saddles_state["register"], {"name": "volume-b",
|
|
|
+ "host": "127.0.0.1:%d" % other.port})
|
|
|
+ check(wait_for(lambda: len(other.register_log) > 0 or False,
|
|
|
+ timeout=15, what="volume-b /register delivery") is not None,
|
|
|
+ "the second saddle received /register")
|
|
|
+ row_b = saddle_row("volume-b")
|
|
|
+ check(row_b is not None and row_b.get("workspace_root") == "/volumes/saddle-b",
|
|
|
+ "the second saddle's reported root lands on its row (%r)"
|
|
|
+ % ((row_b or {}).get("workspace_root")))
|
|
|
+
|
|
|
+ # One task on the demo project, dispatched to EACH saddle in turn:
|
|
|
+ # the assignment's project `path` must sit under the ASKING saddle's
|
|
|
+ # root, not a shared default.
|
|
|
+ def path_of(saddle_fake, title):
|
|
|
+ payloads = [p for p in saddle_fake.start_payloads
|
|
|
+ if (p.get("task") or {}).get("title") == title]
|
|
|
+ if not payloads:
|
|
|
+ return None
|
|
|
+ co = payloads[-1]["task"].get("co_developed") or []
|
|
|
+ return co[0].get("path") if co else None
|
|
|
+
|
|
|
+ # deterministic routing: a capability each saddle alone carries
|
|
|
+ saddles_state = slot_public(auth, "/saddles", "saddles")
|
|
|
+ act(auth, saddles_state["create_capability"], {"name": "primary-vol"})
|
|
|
+ act(auth, slot_public(auth, "/saddles", "saddles")["create_capability"],
|
|
|
+ {"name": "volume-b-vol"})
|
|
|
+ caps = {c["name"]: int(c["id"])
|
|
|
+ for c in slot_public(auth, "/saddles", "saddles")["capabilities"]}
|
|
|
+ act(auth, saddle_card(auth, "fake-saddle")["attach_capability"],
|
|
|
+ {"capability_id": str(caps["primary-vol"])})
|
|
|
+ act(auth, saddle_card(auth, "volume-b")["attach_capability"],
|
|
|
+ {"capability_id": str(caps["volume-b-vol"])})
|
|
|
+
|
|
|
+ def create_routed(title, cap_name, description):
|
|
|
+ task_id = create_queued(auth, {"project_id": "1", "title": title,
|
|
|
+ "description": description, "priority": "2"})
|
|
|
+ act(auth, task_state(auth, task_id)["attach_capability"],
|
|
|
+ {"capability_id": str(caps[cap_name])})
|
|
|
+ wait_for(lambda: [c["name"] for c in
|
|
|
+ task_state(auth, task_id)["capabilities"]] == [cap_name]
|
|
|
+ or False, timeout=30, what="%s attached" % cap_name)
|
|
|
+ return task_id
|
|
|
+
|
|
|
+ first = create_routed("Path probe A", "primary-vol",
|
|
|
+ "Dispatch to the primary volume.")
|
|
|
+ check(wait_for(lambda: path_of(fake, "Path probe A") is not None,
|
|
|
+ timeout=40, what="primary-saddle assignment") is not None,
|
|
|
+ "the primary saddle receives the task")
|
|
|
+ path_a = path_of(fake, "Path probe A")
|
|
|
+ check(path_a is not None and path_a.startswith("/workspace/task-"),
|
|
|
+ "the primary saddle's paths sit under its reported /workspace (%r)" % path_a)
|
|
|
+
|
|
|
+ second = create_routed("Path probe B", "volume-b-vol",
|
|
|
+ "Dispatch to the second volume.")
|
|
|
+ check(wait_for(lambda: path_of(other, "Path probe B") is not None,
|
|
|
+ timeout=40, what="volume-b assignment") is not None,
|
|
|
+ "the volume-b saddle receives the task")
|
|
|
+ path_b = path_of(other, "Path probe B")
|
|
|
+ check(path_b is not None and path_b.startswith("/volumes/saddle-b/task-"),
|
|
|
+ "the volume-b saddle's paths sit under ITS OWN reported root (%r)" % path_b)
|
|
|
+ check(path_a is not None and path_b is not None
|
|
|
+ and path_a.split("/task-")[0] != path_b.split("/task-")[0],
|
|
|
+ "the two saddles' assignments address different volumes")
|
|
|
+
|
|
|
+ print("== origin decoupling: the compat fallback chain ==")
|
|
|
+ # A daemon that does NOT report a workspace_root (pre-task-6 daemon)
|
|
|
+ # keeps a null root; its paths fall back to SADDLE_PROJECTS_ROOT
|
|
|
+ # (the harness runs the app with it pointed at the scratch dir).
|
|
|
+ # The probe task REQUIRES a capability only this saddle carries, so
|
|
|
+ # the dispatcher deterministically targets it (tag routing).
|
|
|
+ legacy = FakeSaddle()
|
|
|
+ legacy.workspace_root = ""
|
|
|
+ legacy.serve(port=free_port())
|
|
|
+ saddles_state = slot_public(auth, "/saddles", "saddles")
|
|
|
+ act(auth, saddles_state["register"],
|
|
|
+ {"name": "legacy-daemon", "host": "127.0.0.1:%d" % legacy.port})
|
|
|
+ check(wait_for(lambda: len(legacy.register_log) > 0 or False,
|
|
|
+ timeout=15, what="legacy /register delivery") is not None,
|
|
|
+ "the legacy daemon received /register")
|
|
|
+ row_legacy = saddle_row("legacy-daemon")
|
|
|
+ check(row_legacy is not None and not row_legacy.get("workspace_root"),
|
|
|
+ "a daemon reporting no root keeps the column empty (%r)"
|
|
|
+ % ((row_legacy or {}).get("workspace_root")))
|
|
|
+ act(auth, slot_public(auth, "/saddles", "saddles")["create_capability"],
|
|
|
+ {"name": "legacy-only"})
|
|
|
+ saddles_state = slot_public(auth, "/saddles", "saddles")
|
|
|
+ legacy_cap = int([c["id"] for c in saddles_state["capabilities"]
|
|
|
+ if c["name"] == "legacy-only"][0])
|
|
|
+ legacy_card = saddle_card(auth, "legacy-daemon")
|
|
|
+ act(auth, legacy_card["attach_capability"], {"capability_id": str(legacy_cap)})
|
|
|
+ third = create_queued(auth, {"project_id": "1", "title": "Path probe C",
|
|
|
+ "description": "Dispatch to the legacy daemon.",
|
|
|
+ "priority": "4"})
|
|
|
+ detail = task_state(auth, third)
|
|
|
+ act(auth, detail["attach_capability"], {"capability_id": str(legacy_cap)})
|
|
|
+ check(wait_for(lambda: [c["name"] for c in
|
|
|
+ task_state(auth, third)["capabilities"]] == ["legacy-only"]
|
|
|
+ or False, timeout=30, what="capability attached") is not None,
|
|
|
+ "the probe task requires the legacy-only capability")
|
|
|
+ check(wait_for(lambda: path_of(legacy, "Path probe C") is not None,
|
|
|
+ timeout=60, what="legacy-saddle assignment") is not None,
|
|
|
+ "the legacy saddle receives the task")
|
|
|
+ path_c = path_of(legacy, "Path probe C")
|
|
|
+ harness_root = os.path.join(WORK, "workspace")
|
|
|
+ check(path_c is not None and path_c.startswith(harness_root + "/task-"),
|
|
|
+ "a null root falls back to SADDLE_PROJECTS_ROOT, not /workspace (%r)" % path_c)
|