hermes: resolve PR follow-ups from their trusted root

This commit is contained in:
jenkins 2026-09-13 16:27:01 -05:00
parent 4d7087d394
commit 38a794c2a9
2 changed files with 12 additions and 4 deletions

View File

@ -111,7 +111,6 @@ def assignment_payload(
encoded = context.encode("utf-8") encoded = context.encode("utf-8")
if len(encoded) > 32 * 1024: if len(encoded) > 32 * 1024:
raise RuntimeError("Kanban worker context exceeds the 32KiB assignment limit") raise RuntimeError("Kanban worker context exceeds the 32KiB assignment limit")
repo_url, branch, base_branch = resolve_scm(task, board)
# Continuation authority comes only from the coordinator-private state DB. # Continuation authority comes only from the coordinator-private state DB.
# Board cards have no metadata column, and their text cannot select a ref. # Board cards have no metadata column, and their text cannot select a ref.
try: try:
@ -120,6 +119,11 @@ def assignment_payload(
raise RuntimeError("supervisor continuation state is unavailable") from error raise RuntimeError("supervisor continuation state is unavailable") from error
lineage = child["lineage"] if child is not None else None lineage = child["lineage"] if child is not None else None
if child is not None: if child is not None:
# A continuation's trusted root record establishes its repository identity.
# Do not consult a pre-existing board checkout here: it can be a
# preserved legacy workspace for another SCM owner and is never the
# private, mediated checkout that will receive this assignment.
repo_url = f"https://scm.bstein.dev/titan/{lineage.project}.git"
root = supervisor_state.get_root(board, lineage.root_task_id) root = supervisor_state.get_root(board, lineage.root_task_id)
parent = str(child.get("parent_task_id") or "") parent = str(child.get("parent_task_id") or "")
if root != lineage or not parent: if root != lineage or not parent:
@ -136,9 +140,10 @@ def assignment_payload(
raise RuntimeError("supervisor continuation parents are invalid") raise RuntimeError("supervisor continuation parents are invalid")
if kanban_db.get_task(connection, lineage.root_task_id) is None: if kanban_db.get_task(connection, lineage.root_task_id) is None:
raise RuntimeError("supervisor continuation root is unavailable") raise RuntimeError("supervisor continuation root is unavailable")
root_task_id = lineage.root_task_id if lineage is not None else str(_task_value(task, "id"))
if lineage is not None:
branch, base_branch = lineage.branch, lineage.base_branch branch, base_branch = lineage.branch, lineage.base_branch
else:
repo_url, branch, base_branch = resolve_scm(task, board)
root_task_id = lineage.root_task_id if lineage is not None else str(_task_value(task, "id"))
runtime = int(_task_value(task, "max_runtime_seconds", 0) or 12 * 60 * 60) runtime = int(_task_value(task, "max_runtime_seconds", 0) or 12 * 60 * 60)
runtime = max(60, min(runtime, 12 * 60 * 60)) runtime = max(60, min(runtime, 12 * 60 * 60))
return { return {

View File

@ -171,7 +171,9 @@ def test_assignment_payload_requires_state_and_native_parents_for_continuations(
monkeypatch.setattr(coordinator.supervisor_state, "get_root", lambda *_args: lineage) monkeypatch.setattr(coordinator.supervisor_state, "get_root", lambda *_args: lineage)
monkeypatch.setattr( monkeypatch.setattr(
coordinator, "resolve_assignment", coordinator, "resolve_assignment",
lambda *_args: ("https://scm.bstein.dev/titan/metis.git", "wrong", "wrong"), lambda *_args: (_ for _ in ()).throw(
AssertionError("trusted continuations must not inspect a legacy checkout")
),
) )
kanban = SimpleNamespace( kanban = SimpleNamespace(
build_worker_context=lambda *_args: "objective", build_worker_context=lambda *_args: "objective",
@ -179,6 +181,7 @@ def test_assignment_payload_requires_state_and_native_parents_for_continuations(
) )
accepted = task(id="repair", parents=("root", "review")) accepted = task(id="repair", parents=("root", "review"))
value = coordinator.assignment_payload(kanban, object(), accepted, "metis") value = coordinator.assignment_payload(kanban, object(), accepted, "metis")
assert value["repo_url"] == "https://scm.bstein.dev/titan/metis.git"
assert value["branch"] == "wt/root" assert value["branch"] == "wt/root"
assert value["continuation_kind"] == "repair" assert value["continuation_kind"] == "repair"
rejected = task(id="repair", parents=("root",)) rejected = task(id="repair", parents=("root",))