fix: durable author worktree resolution without control fallback (Closes #618)
Author mutation tools now resolve workspace via explicit worktree_path,
env bindings, or the active author issue lock — never silent fallback to
the control checkout/master. Missing configured bindings fail closed with
operator recovery; create_issue and create_issue_comment agree.
Recovered onto 0568f44 from preserved candidate cbf56ccd (AUTHOR_RECOVERY).
LLM_LOCK_ID=author-618-recovery-508eb3162d01-1784569919
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
@@ -79,18 +79,33 @@ class TestPreflightIntegration(unittest.TestCase):
|
||||
mcp_server._preflight_whoami_called = True
|
||||
mcp_server._preflight_capability_called = True
|
||||
mcp_server._preflight_resolved_role = "author"
|
||||
mcp_server._preflight_resolved_task = None
|
||||
control_root = "/repo/Gitea-Tools"
|
||||
with mock.patch.object(mcp_server, "PROJECT_ROOT", control_root):
|
||||
with mock.patch.object(mcp_server, "_enforce_root_checkout_guard"):
|
||||
with mock.patch("gitea_auth.get_profile", return_value={"profile_name": "gitea-author"}):
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
with mock.patch(
|
||||
"gitea_mcp_server._session_author_lock_worktree",
|
||||
return_value=None,
|
||||
):
|
||||
with mock.patch(
|
||||
"gitea_auth.get_profile",
|
||||
return_value={"profile_name": "gitea-author"},
|
||||
):
|
||||
with self.assertRaises(RuntimeError) as ctx:
|
||||
mcp_server.verify_preflight_purity()
|
||||
self.assertIn("Branches-only mutation guard", str(ctx.exception))
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
):
|
||||
with self.assertRaises(RuntimeError) as ctx:
|
||||
mcp_server.verify_preflight_purity()
|
||||
blob = str(ctx.exception)
|
||||
self.assertTrue(
|
||||
"Branches-only mutation guard" in blob
|
||||
or "control checkout" in blob
|
||||
or "author worktree" in blob.lower()
|
||||
or "#618" in blob,
|
||||
msg=blob,
|
||||
)
|
||||
|
||||
def test_verify_preflight_allows_branches_worktree(self):
|
||||
import mcp_server
|
||||
@@ -98,14 +113,46 @@ class TestPreflightIntegration(unittest.TestCase):
|
||||
mcp_server._preflight_whoami_called = True
|
||||
mcp_server._preflight_capability_called = True
|
||||
mcp_server._preflight_resolved_role = "author"
|
||||
mcp_server._preflight_resolved_task = None
|
||||
worktree = "/repo/Gitea-Tools/branches/issue-274"
|
||||
healthy_ctx = {
|
||||
"workspace_path": worktree,
|
||||
"workspace_binding_source": "worktree_path argument",
|
||||
"workspace_role_kind": "author",
|
||||
"ignored_bindings": [],
|
||||
"process_project_root": "/repo/Gitea-Tools",
|
||||
"canonical_repo_root": "/repo/Gitea-Tools",
|
||||
"roots_aligned": True,
|
||||
"bound_worktree_missing": False,
|
||||
"author_worktree_block": False,
|
||||
"author_worktree_reasons": [],
|
||||
"author_worktree_resolution": {
|
||||
"proven": True,
|
||||
"block": False,
|
||||
"bound_worktree_missing": False,
|
||||
"workspace_path": worktree,
|
||||
"workspace_binding_source": "worktree_path argument",
|
||||
"reasons": [],
|
||||
},
|
||||
"path_exists": True,
|
||||
"in_git_worktree_list": True,
|
||||
"inspected_git_root": worktree,
|
||||
}
|
||||
with mock.patch.object(mcp_server, "_enforce_root_checkout_guard"):
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
with mock.patch.object(
|
||||
mcp_server, "_session_author_lock_worktree", return_value=None
|
||||
):
|
||||
mcp_server.verify_preflight_purity(worktree_path=worktree)
|
||||
with mock.patch.object(
|
||||
mcp_server,
|
||||
"_resolve_namespace_mutation_context",
|
||||
return_value=healthy_ctx,
|
||||
):
|
||||
with mock.patch.dict(
|
||||
"os.environ",
|
||||
{"GITEA_TEST_PORCELAIN": ""},
|
||||
clear=False,
|
||||
):
|
||||
mcp_server.verify_preflight_purity(worktree_path=worktree)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user