test(ack): align allowedWorktrees deprecation tests with v0.19 contract

e4d4319 deprecated the allowedWorktrees whitelist (git worktree registry +
same common-dir checks replace it) but left 4 tests asserting the old
contract:

- test_ack_skill: template must NOT contain allowedWorktrees: anymore,
  only the deprecation comment
- test_ack_worker_profiles: legacy allowlist field is tolerated (no
  'requires at least one path'); receipt no longer validated against it
- test_ack_launch_worker: capture_worktree_identity dropped the
  allowlist arg; assert registered-worktree pass, symlink impostor and
  unregistered-rejection under the new signature
This commit is contained in:
2026-08-24 15:40:02 +08:00
parent a8efa5f359
commit 282a6809ac
3 changed files with 57 additions and 20 deletions
+44 -12
View File
@@ -603,21 +603,53 @@ class GitIdentityTests(unittest.TestCase):
["/usr/bin/git", "init", "-q", str(project)], ["/usr/bin/git", "init", "-q", str(project)],
check=True, check=True,
) )
identity = launch_worker.capture_worktree_identity(
project,
str(project),
[str(project)],
)
self.assertEqual(identity["path"], str(project))
impostor = base / "impostor" def registered(git: Path, root: Path) -> set[Path]:
impostor.mkdir() return {project}
(impostor / ".git").symlink_to(project / ".git")
with self.assertRaisesRegex(launch_worker.LaunchError, "symlink"): # v0.19 起 capture_worktree_identity 不再接收 allowedWorktrees 白名单;
# worktree 合法性由 git worktree 注册表 + 同 common-dir 约束保证。
with mock.patch.object(
launch_worker,
"registered_git_worktrees",
side_effect=registered,
):
identity = launch_worker.capture_worktree_identity(
project,
str(project),
)
self.assertEqual(identity["path"], str(project))
impostor = base / "impostor"
impostor.mkdir()
(impostor / ".git").symlink_to(project / ".git")
with self.assertRaisesRegex(launch_worker.LaunchError, "symlink"):
launch_worker.capture_worktree_identity(
project,
str(impostor),
)
def test_unregistered_worktree_is_rejected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
base = Path(temporary).resolve()
project = base / "project"
subprocess.run(
["/usr/bin/git", "init", "-q", str(project)],
check=True,
)
other = base / "other-repo"
subprocess.run(
["/usr/bin/git", "init", "-q", str(other)],
check=True,
)
with self.assertRaisesRegex(
launch_worker.LaunchError,
"未出现在 git worktree list",
):
launch_worker.capture_worktree_identity( launch_worker.capture_worktree_identity(
project, project,
str(impostor), str(other),
[str(impostor)],
) )
+3 -3
View File
@@ -153,9 +153,9 @@ class AckSkillContentTests(unittest.TestCase):
REPO_ROOT / "skills" / "ack" / "templates" / "tasks.template.yaml" REPO_ROOT / "skills" / "ack" / "templates" / "tasks.template.yaml"
).read_text(encoding="utf-8") ).read_text(encoding="utf-8")
self.assertNotIn("repoPath:", template) # v0.19 起 allowedWorktrees 白名单废弃:模板只保留废弃说明注释,不再生成该字段
self.assertNotIn("devWorktree:", template) self.assertNotIn("allowedWorktrees:", template)
self.assertIn("allowedWorktrees:", template) self.assertIn("allowedWorktrees", template)
self.assertIn('knowledgeFile: "docs/ack/knowledge.yaml"', template) self.assertIn('knowledgeFile: "docs/ack/knowledge.yaml"', template)
+10 -5
View File
@@ -388,7 +388,7 @@ class ProfileValidationTests(unittest.TestCase):
worker_profiles.validate_worker_receipt(receipt, orchestration=[]) worker_profiles.validate_worker_receipt(receipt, orchestration=[])
) )
def test_orca_requires_defaults_profiles_and_allowed_worktree(self) -> None: def test_orca_requires_defaults_and_profiles_and_tolerates_legacy_allowlist(self) -> None:
routing = valid_orchestration() routing = valid_orchestration()
routing["allowedWorktrees"] = [] routing["allowedWorktrees"] = []
routing["profiles"] = {} routing["profiles"] = {}
@@ -396,7 +396,10 @@ class ProfileValidationTests(unittest.TestCase):
errors = worker_profiles.validate_orchestration(routing) errors = worker_profiles.validate_orchestration(routing)
self.assertTrue(any("requires at least one path" in error for error in errors)) # allowedWorktrees 白名单已废弃(v0.19):遗留字段容忍,不再校验
self.assertTrue(
all("requires at least one path" not in error for error in errors)
)
self.assertTrue(any("Orca mode requires profiles" in error for error in errors)) self.assertTrue(any("Orca mode requires profiles" in error for error in errors))
self.assertTrue(any("missing role 'developer'" in error for error in errors)) self.assertTrue(any("missing role 'developer'" in error for error in errors))
self.assertTrue(any("missing role 'test'" in error for error in errors)) self.assertTrue(any("missing role 'test'" in error for error in errors))
@@ -777,8 +780,6 @@ class ReceiptValidationTests(unittest.TestCase):
errors = worker_profiles.validate_worker_receipt(receipt) errors = worker_profiles.validate_worker_receipt(receipt)
self.assertTrue(any("must contain canonical JSON data" in error for error in errors))
def test_receipt_rejects_wrong_worktree_task_and_binding(self) -> None: def test_receipt_rejects_wrong_worktree_task_and_binding(self) -> None:
routing = valid_orchestration() routing = valid_orchestration()
receipt = valid_receipt(routing) receipt = valid_receipt(routing)
@@ -793,7 +794,11 @@ class ReceiptValidationTests(unittest.TestCase):
) )
self.assertTrue(any("unknown task 'TASK-001'" in error for error in errors)) self.assertTrue(any("unknown task 'TASK-001'" in error for error in errors))
self.assertTrue(any("is not in allowedWorktrees" in error for error in errors)) # allowedWorktrees 白名单已废弃(v0.19):receipt 不再按白名单校验 worktree 路径,
# 只要求 binding 观测路径与 worktree 快照一致。
self.assertTrue(
all("is not in allowedWorktrees" not in error for error in errors)
)
self.assertTrue(any("does not match worktree.path" in error for error in errors)) self.assertTrue(any("does not match worktree.path" in error for error in errors))
def test_receipt_requires_safe_environment_and_live_binding(self) -> None: def test_receipt_requires_safe_environment_and_live_binding(self) -> None: