pyquipu-test-utils 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,75 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # tmpfiles
7
+ o.md
8
+ a.md
9
+ a
10
+ o
11
+ t
12
+ tmpfile
13
+
14
+ # Scaffoldings
15
+ context_builder.yml
16
+ context_builder.py
17
+ current_prompts
18
+
19
+ # Distribution / Packaging
20
+ .Python
21
+ build/
22
+ develop-eggs/
23
+ dist/
24
+ downloads/
25
+ eggs/
26
+ .eggs/
27
+ lib/
28
+ lib64/
29
+ parts/
30
+ sdist/
31
+ var/
32
+ wheels/
33
+ *.egg-info/
34
+ .installed.cfg
35
+ *.egg
36
+
37
+ # Virtual Environments
38
+ venv/
39
+ env/
40
+ .env
41
+ .venv/
42
+
43
+ # Testing
44
+ .tox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # IDEs
55
+ .idea/
56
+ .vscode/
57
+ *.swp
58
+ *.swo
59
+
60
+ # Project Specific
61
+ *.log
62
+ axon.log
63
+ # Ignore test vaults or scratchpads if created in root
64
+ vault/
65
+ temp/
66
+ scratch/
67
+ # --- Quipu Dev Infra ---
68
+ .envs/
69
+ .uv/
70
+ sandbox/
71
+ *.egg-info/
72
+ __pycache__/
73
+ .pytest_cache/
74
+ .coverage
75
+ htmlcov/
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyquipu-test-utils
3
+ Version: 0.1.0
4
+ Summary: Common testing utilities for the Quipu ecosystem.
5
+ Author-email: doucx <doucxldh@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Classifier: Framework :: Pytest
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Programming Language :: Python :: 3
10
+ Requires-Python: >=3.10
11
+ Requires-Dist: pyquipu-bus~=0.1.0
12
+ Requires-Dist: pyquipu-engine~=0.1.0
13
+ Requires-Dist: pyquipu-interfaces~=0.1.0
14
+ Requires-Dist: typer
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pyquipu-test-utils"
7
+ version = "0.1.0"
8
+ authors = [{ name="doucx", email="doucxldh@gmail.com" }]
9
+ description = "Common testing utilities for the Quipu ecosystem."
10
+ requires-python = ">=3.10"
11
+ license = "Apache-2.0"
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "Operating System :: OS Independent",
15
+ "Framework :: Pytest",
16
+ ]
17
+ dependencies = [
18
+ "pyquipu-interfaces ~= 0.1.0",
19
+ "pyquipu-engine ~= 0.1.0",
20
+ "pyquipu-bus ~= 0.1.0",
21
+ "typer"
22
+ ]
23
+
24
+ [tool.uv.sources]
25
+ pyquipu-interfaces = { workspace = true }
26
+ pyquipu-engine = { workspace = true }
27
+ pyquipu-bus = { workspace = true }
28
+
29
+ [tool.hatch.build.targets.wheel]
30
+ packages = ["src/quipu"]
@@ -0,0 +1,3 @@
1
+ # This allows this package to coexist with other distribution packages
2
+ # that contribute to the 'quipu' namespace.
3
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
@@ -0,0 +1,143 @@
1
+ import subprocess
2
+ from pathlib import Path
3
+ from unittest.mock import MagicMock
4
+
5
+ import pytest
6
+ from typer.testing import CliRunner
7
+
8
+ from quipu.engine.git_db import GitDB
9
+ from quipu.engine.git_object_storage import GitObjectHistoryReader, GitObjectHistoryWriter
10
+ from quipu.engine.state_machine import Engine
11
+ from quipu.test_utils.helpers import run_git_command
12
+
13
+ # --- Global & Core Fixtures ---
14
+
15
+
16
+ @pytest.fixture
17
+ def runner() -> CliRunner:
18
+ return CliRunner()
19
+
20
+
21
+ @pytest.fixture
22
+ def git_workspace(tmp_path: Path) -> Path:
23
+ repo_path = tmp_path / "test_repo"
24
+ repo_path.mkdir()
25
+ subprocess.run(["git", "init"], cwd=repo_path, check=True, capture_output=True)
26
+ subprocess.run(["git", "config", "user.email", "test@quipu.dev"], cwd=repo_path, check=True)
27
+ subprocess.run(["git", "config", "user.name", "Quipu Test"], cwd=repo_path, check=True)
28
+ return repo_path
29
+
30
+
31
+ @pytest.fixture
32
+ def engine_instance(git_workspace: Path) -> Engine:
33
+ git_db = GitDB(git_workspace)
34
+ reader = GitObjectHistoryReader(git_db)
35
+ writer = GitObjectHistoryWriter(git_db)
36
+ engine = Engine(root_dir=git_workspace, db=git_db, reader=reader, writer=writer)
37
+ return engine
38
+
39
+
40
+ # --- Application Layer Mocks ---
41
+
42
+
43
+ @pytest.fixture
44
+ def mock_engine():
45
+ engine = MagicMock(spec=Engine)
46
+ # 设置基础属性以防止简单的 AttributeError
47
+ engine.root_dir = Path("/mock/root")
48
+ # 显式初始化 git_db
49
+ engine.git_db = MagicMock()
50
+ # 初始化状态属性
51
+ engine.current_node = None
52
+ engine.history_graph = {}
53
+ return engine
54
+
55
+
56
+ @pytest.fixture
57
+ def mock_runtime():
58
+ # 延迟导入以避免循环依赖或在未安装 runtime 时报错
59
+ from quipu.runtime.executor import Executor
60
+
61
+ runtime = MagicMock(spec=Executor)
62
+ return runtime
63
+
64
+
65
+ # --- CLI Layer Fixtures ---
66
+
67
+
68
+ @pytest.fixture
69
+ def quipu_workspace(engine_instance: Engine):
70
+ return engine_instance.root_dir, engine_instance.git_db, engine_instance
71
+
72
+
73
+ # --- Integration Layer Fixtures ---
74
+
75
+
76
+ @pytest.fixture(scope="module")
77
+ def sync_test_environment(tmp_path_factory):
78
+ base_dir = tmp_path_factory.mktemp("sync_tests")
79
+ remote_path = base_dir / "remote.git"
80
+ user_a_path = base_dir / "user_a"
81
+ user_b_path = base_dir / "user_b"
82
+
83
+ # 1. Create bare remote
84
+ run_git_command(base_dir, ["init", "--bare", str(remote_path)])
85
+
86
+ # 2. Clone for User A
87
+ run_git_command(base_dir, ["clone", str(remote_path), str(user_a_path)])
88
+ run_git_command(user_a_path, ["config", "user.name", "User A"])
89
+ run_git_command(user_a_path, ["config", "user.email", "user.a@example.com"])
90
+
91
+ # 3. Clone for User B
92
+ run_git_command(base_dir, ["clone", str(remote_path), str(user_b_path)])
93
+ run_git_command(user_b_path, ["config", "user.name", "User B"])
94
+ run_git_command(user_b_path, ["config", "user.email", "user.b@example.com"])
95
+
96
+ # Add a dummy file to avoid issues with initial empty commits
97
+ (user_a_path / "README.md").write_text("Initial commit")
98
+ run_git_command(user_a_path, ["add", "README.md"])
99
+ run_git_command(user_a_path, ["commit", "-m", "Initial commit"])
100
+ run_git_command(user_a_path, ["push", "origin", "HEAD"])
101
+ run_git_command(user_b_path, ["pull"])
102
+
103
+ return remote_path, user_a_path, user_b_path
104
+
105
+
106
+ # --- Runtime/Executor Layer Fixtures ---
107
+
108
+
109
+ @pytest.fixture
110
+ def mock_runtime_bus(monkeypatch):
111
+ m_bus = MagicMock()
112
+ # 让 bus.get 返回传入的 msg_id,方便测试断言语义
113
+ m_bus.get.side_effect = lambda msg_id, **kwargs: msg_id
114
+
115
+ patch_targets = [
116
+ "quipu.runtime.executor.bus",
117
+ "quipu.runtime.plugin_loader.bus",
118
+ "quipu.acts.basic.bus",
119
+ "quipu.acts.check.bus",
120
+ "quipu.acts.git.bus",
121
+ "quipu.acts.memory.bus",
122
+ "quipu.acts.read.bus",
123
+ "quipu.acts.refactor.bus",
124
+ "quipu.acts.shell.bus",
125
+ ]
126
+ for target in patch_targets:
127
+ monkeypatch.setattr(target, m_bus, raising=False)
128
+ return m_bus
129
+
130
+
131
+ @pytest.fixture
132
+ def executor(tmp_path: Path):
133
+ from quipu.acts.basic import register as register_basic_acts
134
+ from quipu.runtime.executor import Executor
135
+
136
+ instance = Executor(root_dir=tmp_path, yolo=True)
137
+ register_basic_acts(instance)
138
+ return instance
139
+
140
+
141
+ @pytest.fixture
142
+ def isolated_vault(executor) -> Path:
143
+ return executor.root_dir
@@ -0,0 +1,24 @@
1
+ "engine_instance": |-
2
+ 提供一个绑定到 git_workspace 的、功能完备的 Engine 实例。
3
+ "executor": |-
4
+ 为运行时测试提供一个隔离的 Executor 实例。
5
+ "git_workspace": |-
6
+ 提供一个已初始化 Git 的干净工作区路径。
7
+ "isolated_vault": |-
8
+ 提供 Executor 实例的根工作目录。
9
+ "mock_engine": |-
10
+ 提供一个模拟的 Engine 实例。
11
+ 用于测试 Application 层在不触及真实 Git/文件系统的情况下的编排逻辑。
12
+ "mock_runtime": |-
13
+ 提供一个模拟的 Runtime (Executor) 实例。
14
+ "mock_runtime_bus": |-
15
+ 自动 patch 所有 runtime 模块中导入的 'bus' 实例。
16
+ "quipu_workspace": |-
17
+ 为 CLI 测试提供 Engine 实例及其工作目录。
18
+ 返回: (work_dir_path, git_db, engine)
19
+ "runner": |-
20
+ 提供一个可复用的 CliRunner 实例。
21
+ "sync_test_environment": |-
22
+ Sets up a full sync test environment:
23
+ 1. A bare remote repository.
24
+ 2. Two user workspaces cloned from the remote.
@@ -0,0 +1,418 @@
1
+ import hashlib
2
+ import re
3
+ import subprocess
4
+ import time
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+ from typing import Any, Dict, List, Optional, Set, Tuple
8
+
9
+ from typer.testing import CliRunner
10
+
11
+ from quipu.cli.main import app
12
+ from quipu.engine.state_machine import Engine
13
+ from quipu.interfaces.models import QuipuNode
14
+ from quipu.interfaces.storage import HistoryReader, HistoryWriter
15
+
16
+ # --- Constants ---
17
+
18
+ # The correct hash for an empty git tree.
19
+ EMPTY_TREE_HASH = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
20
+
21
+
22
+ # --- Git-based Test Helpers ---
23
+
24
+
25
+ def create_plan_node_with_change(engine: Engine, parent_hash: str, file_name: str, content: str, message: str) -> str:
26
+ (engine.root_dir / file_name).write_text(content)
27
+ new_hash = engine.git_db.get_tree_hash()
28
+ engine.create_plan_node(input_tree=parent_hash, output_tree=new_hash, plan_content=message)
29
+ return new_hash
30
+
31
+
32
+ def create_capture_node_with_change(engine: Engine, file_name: str, content: str, message: str) -> str:
33
+ (engine.root_dir / file_name).write_text(content)
34
+ new_hash = engine.git_db.get_tree_hash()
35
+ engine.capture_drift(new_hash, message=message)
36
+ return new_hash
37
+
38
+
39
+ # --- In-Memory Backend Mocks for Engine Testing ---
40
+
41
+
42
+ class VirtualFileSystem:
43
+ def __init__(self):
44
+ self._files: Dict[str, str] = {}
45
+
46
+ def write(self, path: str, content: str):
47
+ self._files[path] = content
48
+
49
+ def read(self, path: str) -> Optional[str]:
50
+ return self._files.get(path)
51
+
52
+ def copy(self) -> "VirtualFileSystem":
53
+ new_vfs = VirtualFileSystem()
54
+ new_vfs._files = self._files.copy()
55
+ return new_vfs
56
+
57
+ @property
58
+ def files(self) -> Dict[str, str]:
59
+ return self._files
60
+
61
+
62
+ class InMemoryDB:
63
+ def __init__(self):
64
+ self.vfs = VirtualFileSystem()
65
+ self.snapshots: Dict[str, VirtualFileSystem] = {EMPTY_TREE_HASH: VirtualFileSystem()}
66
+ self.nodes: Dict[str, QuipuNode] = {} # output_tree -> Node
67
+
68
+ def get_tree_hash(self) -> str:
69
+ if not self.vfs.files:
70
+ return EMPTY_TREE_HASH
71
+
72
+ sorted_files = sorted(self.vfs.files.items())
73
+ hasher = hashlib.sha1()
74
+ for path, content in sorted_files:
75
+ hasher.update(path.encode("utf-8"))
76
+ hasher.update(content.encode("utf-8"))
77
+
78
+ tree_hash = hasher.hexdigest()
79
+ if tree_hash not in self.snapshots:
80
+ self.snapshots[tree_hash] = self.vfs.copy()
81
+ return tree_hash
82
+
83
+ def checkout_tree(self, new_tree_hash: str, old_tree_hash: Optional[str] = None):
84
+ # InMemoryDB 总是执行“瞬间切换”,不需要模拟 diff 优化逻辑
85
+ tree_hash = new_tree_hash
86
+ if tree_hash not in self.snapshots:
87
+ raise FileNotFoundError(f"In-memory snapshot not found for hash: {tree_hash}")
88
+ self.vfs = self.snapshots[tree_hash].copy()
89
+
90
+ def get_diff_name_status(self, old_tree: str, new_tree: str) -> List[Tuple[str, str]]:
91
+ old_vfs = self.snapshots.get(old_tree, VirtualFileSystem()).files
92
+ new_vfs = self.snapshots.get(new_tree, VirtualFileSystem()).files
93
+
94
+ old_files = set(old_vfs.keys())
95
+ new_files = set(new_vfs.keys())
96
+
97
+ added = new_files - old_files
98
+ deleted = old_files - new_files
99
+ common = old_files & new_files
100
+
101
+ changes = []
102
+ for f in added:
103
+ changes.append(("A", f))
104
+ for f in deleted:
105
+ changes.append(("D", f))
106
+ for f in common:
107
+ if old_vfs[f] != new_vfs[f]:
108
+ changes.append(("M", f))
109
+ return sorted(changes)
110
+
111
+ def get_diff_stat(self, old_tree: str, new_tree: str) -> str:
112
+ changes = self.get_diff_name_status(old_tree, new_tree)
113
+ return "\n".join(f"{status}\t{path}" for status, path in changes)
114
+
115
+
116
+ class InMemoryHistoryManager(HistoryReader, HistoryWriter):
117
+ def __init__(self, db: InMemoryDB):
118
+ self.db = db # The db holds the single source of truth for nodes
119
+
120
+ def create_node(
121
+ self,
122
+ node_type: str,
123
+ input_tree: str,
124
+ output_tree: str,
125
+ content: str,
126
+ summary_override: Optional[str] = None,
127
+ **kwargs: Any,
128
+ ) -> QuipuNode:
129
+ fake_commit_hash = hashlib.sha1(f"{output_tree}{content}{time.time()}".encode()).hexdigest()
130
+
131
+ node = QuipuNode(
132
+ commit_hash=fake_commit_hash,
133
+ input_tree=input_tree,
134
+ output_tree=output_tree,
135
+ timestamp=datetime.now(),
136
+ filename=Path(f"memory://{fake_commit_hash}"),
137
+ node_type=node_type,
138
+ content=content,
139
+ summary=summary_override or (content.splitlines()[0] if content else f"Node {output_tree[:7]}"),
140
+ )
141
+
142
+ # Correctly link parent upon creation
143
+ if input_tree in self.db.nodes:
144
+ parent_node = self.db.nodes[input_tree]
145
+ node.parent = parent_node
146
+ parent_node.children.append(node)
147
+
148
+ self.db.nodes[output_tree] = node
149
+ return node
150
+
151
+ def load_all_nodes(self) -> List[QuipuNode]:
152
+ # The relationships are already built, just return the list
153
+ return sorted(list(self.db.nodes.values()), key=lambda n: n.timestamp)
154
+
155
+ def get_node_count(self) -> int:
156
+ return len(self.db.nodes)
157
+
158
+ def load_nodes_paginated(self, limit: int, offset: int) -> List[QuipuNode]:
159
+ all_nodes = sorted(self.db.nodes.values(), key=lambda n: n.timestamp, reverse=True)
160
+ return all_nodes[offset : offset + limit]
161
+
162
+ def find_nodes(
163
+ self,
164
+ summary_regex: Optional[str] = None,
165
+ node_type: Optional[str] = None,
166
+ limit: int = 10,
167
+ ) -> List[QuipuNode]:
168
+ candidates = list(self.db.nodes.values())
169
+
170
+ if summary_regex:
171
+ try:
172
+ pattern = re.compile(summary_regex, re.IGNORECASE)
173
+ candidates = [node for node in candidates if pattern.search(node.summary)]
174
+ except re.error:
175
+ return []
176
+
177
+ if node_type:
178
+ candidates = [node for node in candidates if node.node_type == node_type]
179
+
180
+ candidates.sort(key=lambda n: n.timestamp, reverse=True)
181
+ return candidates[:limit]
182
+
183
+ def get_node_content(self, node: QuipuNode) -> str:
184
+ return node.content
185
+
186
+ def get_ancestor_output_trees(self, start_output_tree_hash: str) -> Set[str]:
187
+ ancestors = set()
188
+ if start_output_tree_hash not in self.db.nodes:
189
+ return ancestors
190
+
191
+ curr = self.db.nodes[start_output_tree_hash]
192
+ while curr and curr.parent:
193
+ parent_node = curr.parent
194
+ ancestors.add(parent_node.output_tree)
195
+ curr = parent_node
196
+ return ancestors
197
+
198
+ def get_descendant_output_trees(self, start_output_tree_hash: str) -> Set[str]:
199
+ descendants = set()
200
+ if start_output_tree_hash not in self.db.nodes:
201
+ return descendants
202
+
203
+ queue = [self.db.nodes[start_output_tree_hash]]
204
+ visited = {start_output_tree_hash}
205
+
206
+ while queue:
207
+ current_node = queue.pop(0)
208
+ for child in current_node.children:
209
+ if child.output_tree not in visited:
210
+ descendants.add(child.output_tree)
211
+ visited.add(child.output_tree)
212
+ queue.append(child)
213
+ return descendants
214
+
215
+ def get_node_position(self, output_tree_hash: str) -> int:
216
+ all_nodes = sorted(self.db.nodes.values(), key=lambda n: n.timestamp, reverse=True)
217
+ for i, node in enumerate(all_nodes):
218
+ if node.output_tree == output_tree_hash:
219
+ return i
220
+ return -1
221
+
222
+ def get_private_data(self, node_commit_hash: str) -> Optional[str]:
223
+ return None
224
+
225
+ def get_node_blobs(self, commit_hash: str) -> Dict[str, bytes]:
226
+ return {}
227
+
228
+
229
+ # --- CLI/Integration Test Helpers ---
230
+
231
+
232
+ def run_git_command(cwd: Path, args: list[str], check: bool = True) -> str:
233
+ result = subprocess.run(["git"] + args, cwd=cwd, capture_output=True, text=True, check=check)
234
+ return result.stdout.strip()
235
+
236
+
237
+ def get_local_quipu_heads(work_dir: Path) -> set[str]:
238
+ refs_output = run_git_command(
239
+ work_dir, ["for-each-ref", "--format=%(objectname)", "refs/quipu/local/heads"], check=False
240
+ )
241
+ if not refs_output:
242
+ return set()
243
+ return set(refs_output.splitlines())
244
+
245
+
246
+ def create_node_via_cli(runner: CliRunner, work_dir: Path, content: str) -> str:
247
+ heads_before = get_local_quipu_heads(work_dir)
248
+
249
+ # [FIX] Add an explicit title to the plan to ensure predictable node summary.
250
+ plan_title = f"Plan for {content}"
251
+ plan_file = work_dir / f"{content}.md"
252
+ plan_file.write_text(f"# {plan_title}\n\n~~~~~act\necho '{content}'\n~~~~~")
253
+
254
+ result = runner.invoke(app, ["run", str(plan_file), "--work-dir", str(work_dir), "-y"])
255
+ assert result.exit_code == 0
256
+
257
+ heads_after = get_local_quipu_heads(work_dir)
258
+ new_heads = heads_after - heads_before
259
+
260
+ if not new_heads:
261
+ raise AssertionError("No new Quipu nodes created.")
262
+
263
+ # If only 1 node created, return it.
264
+ if len(new_heads) == 1:
265
+ return new_heads.pop()
266
+
267
+ # If 2 nodes created (Capture + Plan), identify the Plan node by checking if
268
+ # the explicit title is present in the commit message.
269
+ for head in new_heads:
270
+ msg = run_git_command(work_dir, ["log", "-1", "--format=%B", head])
271
+ if plan_title in msg:
272
+ return head
273
+
274
+ raise AssertionError(f"Could not identify Plan node among {len(new_heads)} new heads: {new_heads}")
275
+
276
+
277
+ # --- Engine/Component Test Helpers ---
278
+
279
+
280
+ def create_branching_history(engine: Engine) -> Engine:
281
+ ws = engine.root_dir
282
+ (ws / "file.txt").write_text("v0")
283
+ h0 = engine.git_db.get_tree_hash()
284
+ engine.create_plan_node(EMPTY_TREE_HASH, h0, "plan 0", summary_override="Root Node")
285
+ (ws / "file.txt").write_text("v1")
286
+ h1 = engine.git_db.get_tree_hash()
287
+ engine.create_plan_node(h0, h1, "plan 1", summary_override="Linear Node 1")
288
+ (ws / "file.txt").write_text("v2")
289
+ h2 = engine.git_db.get_tree_hash()
290
+ engine.create_plan_node(h1, h2, "plan 2", summary_override="Branch Point")
291
+ engine.visit(h2)
292
+ (ws / "branch_a.txt").touch()
293
+ h3a = engine.git_db.get_tree_hash()
294
+ engine.create_plan_node(h2, h3a, "plan 3a", summary_override="Branch A change")
295
+ engine.visit(h3a)
296
+ engine.create_plan_node(h3a, h3a, "plan 4", summary_override="Summary Node")
297
+ engine.visit(h2)
298
+ (ws / "branch_b.txt").touch()
299
+ h3b = engine.git_db.get_tree_hash()
300
+ engine.create_plan_node(h2, h3b, "plan 3b", summary_override="Branch B change")
301
+ return engine
302
+
303
+
304
+ def create_complex_link_history(engine: Engine) -> Engine:
305
+ ws = engine.root_dir
306
+ engine.create_plan_node(EMPTY_TREE_HASH, EMPTY_TREE_HASH, "plan sum", summary_override="Ancestor_Summary")
307
+ (ws / "f").write_text("v0")
308
+ h0 = engine.git_db.get_tree_hash()
309
+ engine.create_plan_node(EMPTY_TREE_HASH, h0, "plan 0", summary_override="Root")
310
+ (ws / "f").write_text("v1")
311
+ h1 = engine.git_db.get_tree_hash()
312
+ engine.create_plan_node(h0, h1, "plan 1", summary_override="Branch_Point")
313
+ engine.visit(h1)
314
+ (ws / "a").touch()
315
+ h2a = engine.git_db.get_tree_hash()
316
+ engine.create_plan_node(h1, h2a, "plan 2a", summary_override="Branch_A")
317
+ engine.visit(h1)
318
+ (ws / "b").touch()
319
+ h2b = engine.git_db.get_tree_hash()
320
+ engine.create_plan_node(h1, h2b, "plan 2b", summary_override="Parent_Node")
321
+ engine.visit(h2b)
322
+ (ws / "c").touch()
323
+ h3 = engine.git_db.get_tree_hash()
324
+ engine.create_plan_node(h2b, h3, "plan 3", summary_override="Test_Target_Node")
325
+ engine.visit(h3)
326
+ (ws / "d").touch()
327
+ h4 = engine.git_db.get_tree_hash()
328
+ engine.create_plan_node(h3, h4, "plan 4", summary_override="Child_Node")
329
+ return engine
330
+
331
+
332
+ def create_linear_history(engine: Engine) -> Tuple[Engine, Dict[str, str]]:
333
+ ws = engine.root_dir
334
+
335
+ # State A
336
+ (ws / "a.txt").write_text("A")
337
+ hash_a = engine.git_db.get_tree_hash()
338
+ engine.create_plan_node(EMPTY_TREE_HASH, hash_a, "Plan A", summary_override="State A")
339
+
340
+ # State B
341
+ (ws / "b.txt").write_text("B")
342
+ (ws / "a.txt").unlink()
343
+ hash_b = engine.git_db.get_tree_hash()
344
+ engine.create_plan_node(hash_a, hash_b, "Plan B", summary_override="State B")
345
+
346
+ hashes = {"a": hash_a, "b": hash_b}
347
+ return engine, hashes
348
+
349
+
350
+ def create_dirty_workspace_history(engine: Engine) -> Tuple[Engine, str]:
351
+ work_dir = engine.root_dir
352
+ file_path = work_dir / "file.txt"
353
+
354
+ # State A
355
+ file_path.write_text("v1")
356
+ hash_a = engine.git_db.get_tree_hash()
357
+ engine.capture_drift(hash_a, message="State A")
358
+
359
+ # State B (HEAD)
360
+ file_path.write_text("v2")
361
+ engine.capture_drift(engine.git_db.get_tree_hash(), message="State B")
362
+
363
+ # Dirty State
364
+ file_path.write_text("v3")
365
+
366
+ return engine, hash_a
367
+
368
+
369
+ def create_linear_history_from_specs(engine: Engine, specs: List[Dict[str, Any]]):
370
+ parent_hash = EMPTY_TREE_HASH
371
+ if engine.history_graph:
372
+ # If history is not empty, start from the latest node
373
+ latest_node = sorted(engine.history_graph.values(), key=lambda n: n.timestamp)[-1]
374
+ parent_hash = latest_node.output_tree
375
+
376
+ for i, spec in enumerate(specs):
377
+ # Create a unique file change for each node to ensure a new tree hash
378
+ (engine.root_dir / f"file_{time.time()}_{i}.txt").touch()
379
+ new_hash = engine.git_db.get_tree_hash()
380
+
381
+ if spec["type"] == "plan":
382
+ engine.create_plan_node(
383
+ input_tree=parent_hash,
384
+ output_tree=new_hash,
385
+ plan_content=spec.get("content", ""),
386
+ summary_override=spec["summary"],
387
+ )
388
+ elif spec["type"] == "capture":
389
+ engine.capture_drift(new_hash, message=spec["summary"])
390
+
391
+ parent_hash = new_hash
392
+ # Re-align to ensure the engine's internal graph is fully updated
393
+ engine.align()
394
+
395
+
396
+ def create_query_branching_history(engine: Engine) -> Tuple[Engine, str]:
397
+ ws = engine.root_dir
398
+ # root -> A
399
+ (ws / "f_a").touch()
400
+ h_a = engine.git_db.get_tree_hash()
401
+ node_a = engine.capture_drift(h_a, "Node A")
402
+
403
+ # A -> B (This will become the main branch)
404
+ (ws / "f_b").touch()
405
+ h_b = engine.git_db.get_tree_hash()
406
+ engine.capture_drift(h_b, "Node B")
407
+
408
+ # Go back to A to create the branch
409
+ engine.visit(node_a.output_tree)
410
+
411
+ # A -> C
412
+ (ws / "f_c").touch()
413
+ engine.capture_drift(engine.git_db.get_tree_hash(), "Node C")
414
+
415
+ # Checkout back to B to set it as the current HEAD for the test
416
+ engine.visit(h_b)
417
+ engine.align()
418
+ return engine, h_b
@@ -0,0 +1,49 @@
1
+ "InMemoryDB": |-
2
+ 一个模拟 GitDB 接口的内存数据库,用于快速测试。
3
+ "InMemoryDB.get_tree_hash": |-
4
+ 对当前 VFS 内容进行确定性哈希。
5
+ "InMemoryHistoryManager": |-
6
+ 同时实现 Reader 和 Writer 接口的内存历史管理器。
7
+ "VirtualFileSystem": |-
8
+ 一个简单的内存虚拟文件系统。
9
+ "create_branching_history": |-
10
+ Creates a common branching history for testing.
11
+ History:
12
+ - n0 (root) -> n1 -> n2 (branch point) -> n3a (branch A) -> n4 (summary)
13
+ \-> n3b (branch B)
14
+ "create_capture_node_with_change": |-
15
+ Creates a file change in the workspace and generates a new Capture node.
16
+ The new node is parented to the current HEAD of the engine.
17
+ Returns the output_tree hash of the new node.
18
+ "create_complex_link_history": |-
19
+ Creates a complex history to ensure a specific node has all navigation link types.
20
+ Node n3 will have: a parent (n2b), a child (n4), an ancestor branch point (n1),
21
+ and an ancestor summary node (n_summary).
22
+ "create_dirty_workspace_history": |-
23
+ Creates a history A -> B, then makes the workspace dirty.
24
+ - State A: file.txt -> "v1"
25
+ - State B (HEAD): file.txt -> "v2"
26
+ - Dirty State: file.txt -> "v3"
27
+ Returns the engine and the hash of state A for checkout tests.
28
+ "create_linear_history": |-
29
+ Creates a simple linear history A -> B.
30
+ - State A: a.txt
31
+ - State B: b.txt (a.txt is removed)
32
+ Returns the engine and a dictionary mapping state names ('a', 'b') to their output tree hashes.
33
+ "create_linear_history_from_specs": |-
34
+ Creates a linear history based on a list of specifications.
35
+ Each spec is a dict: {'type': 'plan'|'capture', 'summary': str, 'content': Optional[str]}
36
+ "create_node_via_cli": |-
37
+ Helper to create a node via the CLI runner and return its commit hash.
38
+ "create_plan_node_with_change": |-
39
+ Creates a file change in the workspace and generates a new Plan node.
40
+ Returns the output_tree hash of the new node.
41
+ "create_query_branching_history": |-
42
+ Creates a specific branching history for query reachability tests.
43
+ History: root -> A -> B (HEAD)
44
+ \-> C (unreachable)
45
+ Returns the engine and the hash of state B (the HEAD).
46
+ "get_local_quipu_heads": |-
47
+ Helper to get a set of all local quipu head commit hashes.
48
+ "run_git_command": |-
49
+ Helper to run a git command and return stdout.
@@ -0,0 +1,422 @@
1
+ {
2
+ "fingerprints": {
3
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#engine_instance": {
4
+ "baseline_code_signature_text": "def engine_instance(git_workspace: Path) -> Engine:",
5
+ "baseline_code_structure_hash": "508b467f12049f2a128a83de3b3bf26762a4f37b630e28c4eab7f4c34630d020",
6
+ "baseline_yaml_content_hash": "db9af6f9ab08827b717045437dfcef2083d7963fc22ccec3ebddb6b7c287f86c"
7
+ },
8
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#executor": {
9
+ "baseline_code_signature_text": "def executor(tmp_path: Path):",
10
+ "baseline_code_structure_hash": "828bede5f3d6f8a39a42fb146f9ac9e2121d63b156b32cbb46241212812b1942",
11
+ "baseline_yaml_content_hash": "45e3c92865ee2aa7de7efbaa80250df0f55de2ef095240af011945389b506487"
12
+ },
13
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#git_workspace": {
14
+ "baseline_code_signature_text": "def git_workspace(tmp_path: Path) -> Path:",
15
+ "baseline_code_structure_hash": "212c48cd2bfdcb11d1b5cfa9bb9aacd9a8b97a695863b62ebbfabbfdcc3c4ebf",
16
+ "baseline_yaml_content_hash": "9acade793a04a427d40fea92e189056736a0176ca744f8a80c4b317de861e9c2"
17
+ },
18
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#isolated_vault": {
19
+ "baseline_code_signature_text": "def isolated_vault(executor) -> Path:",
20
+ "baseline_code_structure_hash": "4266808927f59d2f83309312cbfbe27adce4d15f5be9898b63a4246c41dcff7c",
21
+ "baseline_yaml_content_hash": "4564ac7af7fe857ce674e09d77054ec16cea7177a5510422e3527500986e3794"
22
+ },
23
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#mock_engine": {
24
+ "baseline_code_signature_text": "def mock_engine():",
25
+ "baseline_code_structure_hash": "356e9fb160aafb3b3dff193494c8ec9808994d6794585f82c0f088c667dae738",
26
+ "baseline_yaml_content_hash": "d452e33e4d45988715261d1ac74d72568a97a3b58678054e3f2755330f988cd7"
27
+ },
28
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#mock_runtime": {
29
+ "baseline_code_signature_text": "def mock_runtime():",
30
+ "baseline_code_structure_hash": "33afd9208fd13d1928de8848342ed791bf13f87918ea571de8ad156a621eca13",
31
+ "baseline_yaml_content_hash": "328e7d4a0cdf5e44f753ec79e30ed151db691dc806ac7aea9368fc57e17d1f03"
32
+ },
33
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#mock_runtime_bus": {
34
+ "baseline_code_signature_text": "def mock_runtime_bus(monkeypatch):",
35
+ "baseline_code_structure_hash": "7cf21c2a06934f4c8699dfc2ede7d34009da427cb32a86b3c32fb864ef905462",
36
+ "baseline_yaml_content_hash": "b5df45efe6096cbcb714abce7bbc1622d6c9e15567e715875e23b646fcff972a"
37
+ },
38
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#quipu_workspace": {
39
+ "baseline_code_signature_text": "def quipu_workspace(engine_instance: Engine):",
40
+ "baseline_code_structure_hash": "802bd8d11b57f1ad06b0e92bb5f75d8cc3f2dc544f299177179d13f01bcaa448",
41
+ "baseline_yaml_content_hash": "a2b612e297794a1d66d50d7b24b1cbfc6c181647ce34ebdf95599f7b44e07101"
42
+ },
43
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#runner": {
44
+ "baseline_code_signature_text": "def runner() -> CliRunner:",
45
+ "baseline_code_structure_hash": "261ea21cb8282c88236db52b977b2618b009387fcd2317c1fdba9666e1ac4587",
46
+ "baseline_yaml_content_hash": "c494b687eac604601096a641a5bf66943175ad538f97595ae6c8e07b07bea26d"
47
+ },
48
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/fixtures.py#sync_test_environment": {
49
+ "baseline_code_signature_text": "def sync_test_environment(tmp_path_factory):",
50
+ "baseline_code_structure_hash": "24a3961ed104cd64fdc6f9bb10972cdb4da79c48651ffc5368c42b00134f6149",
51
+ "baseline_yaml_content_hash": "356e155289d0fda418d23a3f8fa386da6348b2f15a7e645b79c0c9c648634cc8"
52
+ },
53
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryDB": {
54
+ "baseline_code_signature_text": "class InMemoryDB:",
55
+ "baseline_code_structure_hash": "9e05bbd44314ebe643651d8910de5c0e60ec7232d4b08be981721d658f7f789f",
56
+ "baseline_yaml_content_hash": "11b2d1a19410e45345c134bbfb75a1b9c458f3d600d96d1013a483ca24d113d5"
57
+ },
58
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryDB.__init__": {
59
+ "baseline_code_signature_text": "def __init__(self):",
60
+ "baseline_code_structure_hash": "9bab2b1dd22fea04e58176b09f65ef4f673738c47abf25fca7e0c62af472206f"
61
+ },
62
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryDB.checkout_tree": {
63
+ "baseline_code_signature_text": "def checkout_tree(self, new_tree_hash: str, old_tree_hash: Optional[str] = None):",
64
+ "baseline_code_structure_hash": "5665baaadaf6a2b3e5f09812ec429cd57f9cd0ee96ec6a6fd9b574de0638f5a5"
65
+ },
66
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryDB.get_diff_name_status": {
67
+ "baseline_code_signature_text": "def get_diff_name_status(self, old_tree: str, new_tree: str) -> List[Tuple[str, str]]:",
68
+ "baseline_code_structure_hash": "807343877a65b864a254b3e3719d15a6cc0edb17c4e792ea1bba00c60f0be910"
69
+ },
70
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryDB.get_diff_stat": {
71
+ "baseline_code_signature_text": "def get_diff_stat(self, old_tree: str, new_tree: str) -> str:",
72
+ "baseline_code_structure_hash": "ce6f966e1089f6eb26f95e61986f232700fdcaf765f9b31111d9d7ebb473ea47"
73
+ },
74
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryDB.get_tree_hash": {
75
+ "baseline_code_signature_text": "def get_tree_hash(self) -> str:",
76
+ "baseline_code_structure_hash": "9fd88b05fd5c0e70ea2ea2a59b07ed091770257177751914385e56deeb306eff",
77
+ "baseline_yaml_content_hash": "59bf4c81e53df8a20316d26ec93e0d11c6a550264bf897046a8e3adfbbe2ab2b"
78
+ },
79
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager": {
80
+ "baseline_code_signature_text": "class InMemoryHistoryManager(HistoryReader, HistoryWriter):",
81
+ "baseline_code_structure_hash": "962a4a8935d136f0b54dc8726d0cc5217fa021b39711045bc87661df1602286f",
82
+ "baseline_yaml_content_hash": "258740eea91ab75bf94fa5ab1aed5ec584df07b6f9be4c583ea06499727330a3"
83
+ },
84
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.__init__": {
85
+ "baseline_code_signature_text": "def __init__(self, db: InMemoryDB):",
86
+ "baseline_code_structure_hash": "d83218c094372a8d28cf658577483ef46c9069b26b63410c35e75ace59ba0329"
87
+ },
88
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.create_node": {
89
+ "baseline_code_signature_text": "def create_node(self, node_type: str, input_tree: str, output_tree: str, content: str, summary_override: Optional[str] = None, **kwargs: Any = {}) -> QuipuNode:",
90
+ "baseline_code_structure_hash": "0b3e983f67b1351f7a4361e31a7c9144d1988621951d626bf72c09424a75d639"
91
+ },
92
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.find_nodes": {
93
+ "baseline_code_signature_text": "def find_nodes(self, summary_regex: Optional[str] = None, node_type: Optional[str] = None, limit: int = 10) -> List[QuipuNode]:",
94
+ "baseline_code_structure_hash": "3d04cb357877311ed8d37041f5ad5d0f322ed4105e52f5b88cfd40b6f110f6cc"
95
+ },
96
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.get_ancestor_output_trees": {
97
+ "baseline_code_signature_text": "def get_ancestor_output_trees(self, start_output_tree_hash: str) -> Set[str]:",
98
+ "baseline_code_structure_hash": "5ae091ca177977fc323d5563cb7f0c6e7af44ac50237f951d24c9793c2336220"
99
+ },
100
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.get_descendant_output_trees": {
101
+ "baseline_code_signature_text": "def get_descendant_output_trees(self, start_output_tree_hash: str) -> Set[str]:",
102
+ "baseline_code_structure_hash": "8eb09e56e11e9534720ef7286af9a75507b606322ada07811813f6b3278f5edd"
103
+ },
104
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_blobs": {
105
+ "baseline_code_signature_text": "def get_node_blobs(self, commit_hash: str) -> Dict[str, bytes]:",
106
+ "baseline_code_structure_hash": "48acf7a37a5612c09d5062797e966133a5c15ba17d05e10407be3235bb076f3d"
107
+ },
108
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_content": {
109
+ "baseline_code_signature_text": "def get_node_content(self, node: QuipuNode) -> str:",
110
+ "baseline_code_structure_hash": "72fb728d5fb5468b523a77045d87750229fb34202f36e0bfe8861de1ab999ed8"
111
+ },
112
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_count": {
113
+ "baseline_code_signature_text": "def get_node_count(self) -> int:",
114
+ "baseline_code_structure_hash": "f248a486494c998cc0f98482e50a5e3292f3132d247377d5088251762489517e"
115
+ },
116
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_position": {
117
+ "baseline_code_signature_text": "def get_node_position(self, output_tree_hash: str) -> int:",
118
+ "baseline_code_structure_hash": "eeb815e029cbffaf43c5365481a21a4251ca6fb30632886a63a5716104041b0e"
119
+ },
120
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.get_private_data": {
121
+ "baseline_code_signature_text": "def get_private_data(self, node_commit_hash: str) -> Optional[str]:",
122
+ "baseline_code_structure_hash": "b03c5152ce31de33095b38682a69df3dcfcd6551fd2d0e5109137fb9a8e6a772"
123
+ },
124
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.load_all_nodes": {
125
+ "baseline_code_signature_text": "def load_all_nodes(self) -> List[QuipuNode]:",
126
+ "baseline_code_structure_hash": "860f1b0ce953562bf9798d8e0e7a6d05c0aada817fc5e88689012cb45876f7be"
127
+ },
128
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#InMemoryHistoryManager.load_nodes_paginated": {
129
+ "baseline_code_signature_text": "def load_nodes_paginated(self, limit: int, offset: int) -> List[QuipuNode]:",
130
+ "baseline_code_structure_hash": "cf4d892bf90a00fa3f083ef8e4bb292b58bf36a417cf53e04002657744c0022e"
131
+ },
132
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#VirtualFileSystem": {
133
+ "baseline_code_signature_text": "class VirtualFileSystem:",
134
+ "baseline_code_structure_hash": "6bee4fef645ed9178324a9e0eb454ed5ebac015954e168eb51cba2553caaf325",
135
+ "baseline_yaml_content_hash": "c378a76357a9a1ccc65099769acf450a9accb6936ab4c5c3f6411092374d9609"
136
+ },
137
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#VirtualFileSystem.__init__": {
138
+ "baseline_code_signature_text": "def __init__(self):",
139
+ "baseline_code_structure_hash": "9bab2b1dd22fea04e58176b09f65ef4f673738c47abf25fca7e0c62af472206f"
140
+ },
141
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#VirtualFileSystem.copy": {
142
+ "baseline_code_signature_text": "def copy(self) -> VirtualFileSystem:",
143
+ "baseline_code_structure_hash": "568018bce5cb8d6b0a2a72c2f8d4dc40dfc67db2792096d93e525d1ff339d823"
144
+ },
145
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#VirtualFileSystem.read": {
146
+ "baseline_code_signature_text": "def read(self, path: str) -> Optional[str]:",
147
+ "baseline_code_structure_hash": "610c3197a70c8c4e0dc5ddd1a636a625ed5cda307bdbca93d0fb017850a06d1c"
148
+ },
149
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#VirtualFileSystem.write": {
150
+ "baseline_code_signature_text": "def write(self, path: str, content: str):",
151
+ "baseline_code_structure_hash": "50fd606d639eaaac881ea1fa5f2f2a97c4919d258818e279b911bc1f4d7031b3"
152
+ },
153
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_branching_history": {
154
+ "baseline_code_signature_text": "def create_branching_history(engine: Engine) -> Engine:",
155
+ "baseline_code_structure_hash": "df7ba659995fe344b131ba341c3e5941b1f2b7fae977485e0dd0d5ff9b7fa337",
156
+ "baseline_yaml_content_hash": "cf0e780d4c2f506aa8493a79c7785859dbe57be0ff0d391ec4ae016583a0d7bf"
157
+ },
158
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_capture_node_with_change": {
159
+ "baseline_code_signature_text": "def create_capture_node_with_change(engine: Engine, file_name: str, content: str, message: str) -> str:",
160
+ "baseline_code_structure_hash": "494564c8a001bce88c6cf3e5c16759210b0516459d7d4c23619b1130504d5401",
161
+ "baseline_yaml_content_hash": "352884bfbba30a002a2e79028f2abacfbd751ba35198cccde6104a75cb4e9350"
162
+ },
163
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_complex_link_history": {
164
+ "baseline_code_signature_text": "def create_complex_link_history(engine: Engine) -> Engine:",
165
+ "baseline_code_structure_hash": "9b3bf012779979584d371aa9e851f4880c5e330650aae5e1981bf4ed570fbf0d",
166
+ "baseline_yaml_content_hash": "2b18d49fe70c484ef9eb7e30b82ef7947626997888fc200007e9bc82bbb52049"
167
+ },
168
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_dirty_workspace_history": {
169
+ "baseline_code_signature_text": "def create_dirty_workspace_history(engine: Engine) -> Tuple[Engine, str]:",
170
+ "baseline_code_structure_hash": "9a1b473936bc06f3c7c301e66140295213df44abc420f8775246d5987b8c1cb0",
171
+ "baseline_yaml_content_hash": "788b7ec1efaaeb6e6b78fdfd2bdd37d2e351d623d9295291c369478832bb739d"
172
+ },
173
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_linear_history": {
174
+ "baseline_code_signature_text": "def create_linear_history(engine: Engine) -> Tuple[Engine, Dict[str, str]]:",
175
+ "baseline_code_structure_hash": "3ada516acb039d0433939843fde70504f99dee0302a1342292fc8d6c9fabf883",
176
+ "baseline_yaml_content_hash": "2b2e026a825ce169baf9da35d706d1e55fa1ca76af4b7605e78bcbc2e6383599"
177
+ },
178
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_linear_history_from_specs": {
179
+ "baseline_code_signature_text": "def create_linear_history_from_specs(engine: Engine, specs: List[Dict[str, Any]]):",
180
+ "baseline_code_structure_hash": "4e0464d5d219a29b0877daa0db5127754a0527bb0e2ce2b667521475b6913f19",
181
+ "baseline_yaml_content_hash": "c7ec7be674a17ad41caac42e79b2950813e70941b054b8b5f6b758a28b36722d"
182
+ },
183
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_node_via_cli": {
184
+ "baseline_code_signature_text": "def create_node_via_cli(runner: CliRunner, work_dir: Path, content: str) -> str:",
185
+ "baseline_code_structure_hash": "5d80af898918da29c7bf47de2fc50c82d26e55da1ed94e52cf8706bd7b84c9d8",
186
+ "baseline_yaml_content_hash": "e4aa9c4168e56c0a2f57abc6a79b10ac7853ab019b0c30b5582b0cc12dcf5577"
187
+ },
188
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_plan_node_with_change": {
189
+ "baseline_code_signature_text": "def create_plan_node_with_change(engine: Engine, parent_hash: str, file_name: str, content: str, message: str) -> str:",
190
+ "baseline_code_structure_hash": "cf61ae48f737c72cd80bbfb1fb68af0b154ff553270f31e181603b9445bc2022",
191
+ "baseline_yaml_content_hash": "8c2dc8174d13fa669d9125a57591161fa3153ad590205eeada686934077fbcb7"
192
+ },
193
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#create_query_branching_history": {
194
+ "baseline_code_signature_text": "def create_query_branching_history(engine: Engine) -> Tuple[Engine, str]:",
195
+ "baseline_code_structure_hash": "b5df830ed85fcd3b85c442eadaf3dfbe4ccc48a4f81f70f89bc0d94d02ea232e",
196
+ "baseline_yaml_content_hash": "2b33e55e9b1b15627669e69594fbb8287dac86b82599fb48aa339605fc480ac8"
197
+ },
198
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#get_local_quipu_heads": {
199
+ "baseline_code_signature_text": "def get_local_quipu_heads(work_dir: Path) -> set[str]:",
200
+ "baseline_code_structure_hash": "98f18e5a64b1643d42f06af5b609169f653f638e973dd802ce642250bd754793",
201
+ "baseline_yaml_content_hash": "568480bdd2b8aa9ef17a3754a68a6013415adf9bcf951544c00d593c28cfb1b6"
202
+ },
203
+ "py://packages/pyquipu-test-utils/src/quipu/test_utils/helpers.py#run_git_command": {
204
+ "baseline_code_signature_text": "def run_git_command(cwd: Path, args: list[str], check: bool = True) -> str:",
205
+ "baseline_code_structure_hash": "ab5208c68cb72aff451337e18f15003513c4e1c630a1f8604568417243f200d7",
206
+ "baseline_yaml_content_hash": "362d9c62b2f1936e5224993c2a2aad1fb3550f95a81f599d1f4d299e34b97b4c"
207
+ },
208
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#engine_instance": {
209
+ "baseline_code_signature_text": "def engine_instance(git_workspace: Path) -> Engine:",
210
+ "baseline_code_structure_hash": "508b467f12049f2a128a83de3b3bf26762a4f37b630e28c4eab7f4c34630d020",
211
+ "baseline_yaml_content_hash": "db9af6f9ab08827b717045437dfcef2083d7963fc22ccec3ebddb6b7c287f86c"
212
+ },
213
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#executor": {
214
+ "baseline_code_signature_text": "def executor(tmp_path: Path):",
215
+ "baseline_code_structure_hash": "828bede5f3d6f8a39a42fb146f9ac9e2121d63b156b32cbb46241212812b1942",
216
+ "baseline_yaml_content_hash": "45e3c92865ee2aa7de7efbaa80250df0f55de2ef095240af011945389b506487"
217
+ },
218
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#git_workspace": {
219
+ "baseline_code_signature_text": "def git_workspace(tmp_path: Path) -> Path:",
220
+ "baseline_code_structure_hash": "212c48cd2bfdcb11d1b5cfa9bb9aacd9a8b97a695863b62ebbfabbfdcc3c4ebf",
221
+ "baseline_yaml_content_hash": "9acade793a04a427d40fea92e189056736a0176ca744f8a80c4b317de861e9c2"
222
+ },
223
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#isolated_vault": {
224
+ "baseline_code_signature_text": "def isolated_vault(executor) -> Path:",
225
+ "baseline_code_structure_hash": "4266808927f59d2f83309312cbfbe27adce4d15f5be9898b63a4246c41dcff7c",
226
+ "baseline_yaml_content_hash": "4564ac7af7fe857ce674e09d77054ec16cea7177a5510422e3527500986e3794"
227
+ },
228
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#mock_engine": {
229
+ "baseline_code_signature_text": "def mock_engine():",
230
+ "baseline_code_structure_hash": "356e9fb160aafb3b3dff193494c8ec9808994d6794585f82c0f088c667dae738",
231
+ "baseline_yaml_content_hash": "d452e33e4d45988715261d1ac74d72568a97a3b58678054e3f2755330f988cd7"
232
+ },
233
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#mock_runtime": {
234
+ "baseline_code_signature_text": "def mock_runtime():",
235
+ "baseline_code_structure_hash": "33afd9208fd13d1928de8848342ed791bf13f87918ea571de8ad156a621eca13",
236
+ "baseline_yaml_content_hash": "328e7d4a0cdf5e44f753ec79e30ed151db691dc806ac7aea9368fc57e17d1f03"
237
+ },
238
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#mock_runtime_bus": {
239
+ "baseline_code_signature_text": "def mock_runtime_bus(monkeypatch):",
240
+ "baseline_code_structure_hash": "7cf21c2a06934f4c8699dfc2ede7d34009da427cb32a86b3c32fb864ef905462",
241
+ "baseline_yaml_content_hash": "b5df45efe6096cbcb714abce7bbc1622d6c9e15567e715875e23b646fcff972a"
242
+ },
243
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#quipu_workspace": {
244
+ "baseline_code_signature_text": "def quipu_workspace(engine_instance: Engine):",
245
+ "baseline_code_structure_hash": "802bd8d11b57f1ad06b0e92bb5f75d8cc3f2dc544f299177179d13f01bcaa448",
246
+ "baseline_yaml_content_hash": "a2b612e297794a1d66d50d7b24b1cbfc6c181647ce34ebdf95599f7b44e07101"
247
+ },
248
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#runner": {
249
+ "baseline_code_signature_text": "def runner() -> CliRunner:",
250
+ "baseline_code_structure_hash": "261ea21cb8282c88236db52b977b2618b009387fcd2317c1fdba9666e1ac4587",
251
+ "baseline_yaml_content_hash": "c494b687eac604601096a641a5bf66943175ad538f97595ae6c8e07b07bea26d"
252
+ },
253
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/fixtures.py#sync_test_environment": {
254
+ "baseline_code_signature_text": "def sync_test_environment(tmp_path_factory):",
255
+ "baseline_code_structure_hash": "24a3961ed104cd64fdc6f9bb10972cdb4da79c48651ffc5368c42b00134f6149",
256
+ "baseline_yaml_content_hash": "356e155289d0fda418d23a3f8fa386da6348b2f15a7e645b79c0c9c648634cc8"
257
+ },
258
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#EMPTY_TREE_HASH": {},
259
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB": {
260
+ "baseline_code_signature_text": "class InMemoryDB:",
261
+ "baseline_code_structure_hash": "9e05bbd44314ebe643651d8910de5c0e60ec7232d4b08be981721d658f7f789f",
262
+ "baseline_yaml_content_hash": "11b2d1a19410e45345c134bbfb75a1b9c458f3d600d96d1013a483ca24d113d5"
263
+ },
264
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.__init__": {
265
+ "baseline_code_signature_text": "def __init__(self):",
266
+ "baseline_code_structure_hash": "9bab2b1dd22fea04e58176b09f65ef4f673738c47abf25fca7e0c62af472206f"
267
+ },
268
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.checkout_tree": {
269
+ "baseline_code_signature_text": "def checkout_tree(self, new_tree_hash: str, old_tree_hash: Optional[str] = None):",
270
+ "baseline_code_structure_hash": "5665baaadaf6a2b3e5f09812ec429cd57f9cd0ee96ec6a6fd9b574de0638f5a5"
271
+ },
272
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.get_diff_name_status": {
273
+ "baseline_code_signature_text": "def get_diff_name_status(self, old_tree: str, new_tree: str) -> List[Tuple[str, str]]:",
274
+ "baseline_code_structure_hash": "807343877a65b864a254b3e3719d15a6cc0edb17c4e792ea1bba00c60f0be910"
275
+ },
276
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.get_diff_stat": {
277
+ "baseline_code_signature_text": "def get_diff_stat(self, old_tree: str, new_tree: str) -> str:",
278
+ "baseline_code_structure_hash": "ce6f966e1089f6eb26f95e61986f232700fdcaf765f9b31111d9d7ebb473ea47"
279
+ },
280
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.get_tree_hash": {
281
+ "baseline_code_signature_text": "def get_tree_hash(self) -> str:",
282
+ "baseline_code_structure_hash": "9fd88b05fd5c0e70ea2ea2a59b07ed091770257177751914385e56deeb306eff",
283
+ "baseline_yaml_content_hash": "59bf4c81e53df8a20316d26ec93e0d11c6a550264bf897046a8e3adfbbe2ab2b"
284
+ },
285
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.nodes": {},
286
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.snapshots": {},
287
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryDB.vfs": {},
288
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager": {
289
+ "baseline_code_signature_text": "class InMemoryHistoryManager(HistoryReader, HistoryWriter):",
290
+ "baseline_code_structure_hash": "962a4a8935d136f0b54dc8726d0cc5217fa021b39711045bc87661df1602286f",
291
+ "baseline_yaml_content_hash": "258740eea91ab75bf94fa5ab1aed5ec584df07b6f9be4c583ea06499727330a3"
292
+ },
293
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.__init__": {
294
+ "baseline_code_signature_text": "def __init__(self, db: InMemoryDB):",
295
+ "baseline_code_structure_hash": "d83218c094372a8d28cf658577483ef46c9069b26b63410c35e75ace59ba0329"
296
+ },
297
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.create_node": {
298
+ "baseline_code_signature_text": "def create_node(self, node_type: str, input_tree: str, output_tree: str, content: str, summary_override: Optional[str] = None, **kwargs: Any = {}) -> QuipuNode:",
299
+ "baseline_code_structure_hash": "0b3e983f67b1351f7a4361e31a7c9144d1988621951d626bf72c09424a75d639"
300
+ },
301
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.db": {},
302
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.find_nodes": {
303
+ "baseline_code_signature_text": "def find_nodes(self, summary_regex: Optional[str] = None, node_type: Optional[str] = None, limit: int = 10) -> List[QuipuNode]:",
304
+ "baseline_code_structure_hash": "3d04cb357877311ed8d37041f5ad5d0f322ed4105e52f5b88cfd40b6f110f6cc"
305
+ },
306
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.get_ancestor_output_trees": {
307
+ "baseline_code_signature_text": "def get_ancestor_output_trees(self, start_output_tree_hash: str) -> Set[str]:",
308
+ "baseline_code_structure_hash": "5ae091ca177977fc323d5563cb7f0c6e7af44ac50237f951d24c9793c2336220"
309
+ },
310
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.get_descendant_output_trees": {
311
+ "baseline_code_signature_text": "def get_descendant_output_trees(self, start_output_tree_hash: str) -> Set[str]:",
312
+ "baseline_code_structure_hash": "8eb09e56e11e9534720ef7286af9a75507b606322ada07811813f6b3278f5edd"
313
+ },
314
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_blobs": {
315
+ "baseline_code_signature_text": "def get_node_blobs(self, commit_hash: str) -> Dict[str, bytes]:",
316
+ "baseline_code_structure_hash": "48acf7a37a5612c09d5062797e966133a5c15ba17d05e10407be3235bb076f3d"
317
+ },
318
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_content": {
319
+ "baseline_code_signature_text": "def get_node_content(self, node: QuipuNode) -> str:",
320
+ "baseline_code_structure_hash": "72fb728d5fb5468b523a77045d87750229fb34202f36e0bfe8861de1ab999ed8"
321
+ },
322
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_count": {
323
+ "baseline_code_signature_text": "def get_node_count(self) -> int:",
324
+ "baseline_code_structure_hash": "f248a486494c998cc0f98482e50a5e3292f3132d247377d5088251762489517e"
325
+ },
326
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.get_node_position": {
327
+ "baseline_code_signature_text": "def get_node_position(self, output_tree_hash: str) -> int:",
328
+ "baseline_code_structure_hash": "eeb815e029cbffaf43c5365481a21a4251ca6fb30632886a63a5716104041b0e"
329
+ },
330
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.get_private_data": {
331
+ "baseline_code_signature_text": "def get_private_data(self, node_commit_hash: str) -> Optional[str]:",
332
+ "baseline_code_structure_hash": "b03c5152ce31de33095b38682a69df3dcfcd6551fd2d0e5109137fb9a8e6a772"
333
+ },
334
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.load_all_nodes": {
335
+ "baseline_code_signature_text": "def load_all_nodes(self) -> List[QuipuNode]:",
336
+ "baseline_code_structure_hash": "860f1b0ce953562bf9798d8e0e7a6d05c0aada817fc5e88689012cb45876f7be"
337
+ },
338
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#InMemoryHistoryManager.load_nodes_paginated": {
339
+ "baseline_code_signature_text": "def load_nodes_paginated(self, limit: int, offset: int) -> List[QuipuNode]:",
340
+ "baseline_code_structure_hash": "cf4d892bf90a00fa3f083ef8e4bb292b58bf36a417cf53e04002657744c0022e"
341
+ },
342
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#VirtualFileSystem": {
343
+ "baseline_code_signature_text": "class VirtualFileSystem:",
344
+ "baseline_code_structure_hash": "6bee4fef645ed9178324a9e0eb454ed5ebac015954e168eb51cba2553caaf325",
345
+ "baseline_yaml_content_hash": "c378a76357a9a1ccc65099769acf450a9accb6936ab4c5c3f6411092374d9609"
346
+ },
347
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#VirtualFileSystem.__init__": {
348
+ "baseline_code_signature_text": "def __init__(self):",
349
+ "baseline_code_structure_hash": "9bab2b1dd22fea04e58176b09f65ef4f673738c47abf25fca7e0c62af472206f"
350
+ },
351
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#VirtualFileSystem._files": {},
352
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#VirtualFileSystem.copy": {
353
+ "baseline_code_signature_text": "def copy(self) -> VirtualFileSystem:",
354
+ "baseline_code_structure_hash": "568018bce5cb8d6b0a2a72c2f8d4dc40dfc67db2792096d93e525d1ff339d823"
355
+ },
356
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#VirtualFileSystem.files": {},
357
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#VirtualFileSystem.read": {
358
+ "baseline_code_signature_text": "def read(self, path: str) -> Optional[str]:",
359
+ "baseline_code_structure_hash": "610c3197a70c8c4e0dc5ddd1a636a625ed5cda307bdbca93d0fb017850a06d1c"
360
+ },
361
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#VirtualFileSystem.write": {
362
+ "baseline_code_signature_text": "def write(self, path: str, content: str):",
363
+ "baseline_code_structure_hash": "50fd606d639eaaac881ea1fa5f2f2a97c4919d258818e279b911bc1f4d7031b3"
364
+ },
365
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_branching_history": {
366
+ "baseline_code_signature_text": "def create_branching_history(engine: Engine) -> Engine:",
367
+ "baseline_code_structure_hash": "df7ba659995fe344b131ba341c3e5941b1f2b7fae977485e0dd0d5ff9b7fa337",
368
+ "baseline_yaml_content_hash": "cf0e780d4c2f506aa8493a79c7785859dbe57be0ff0d391ec4ae016583a0d7bf"
369
+ },
370
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_capture_node_with_change": {
371
+ "baseline_code_signature_text": "def create_capture_node_with_change(engine: Engine, file_name: str, content: str, message: str) -> str:",
372
+ "baseline_code_structure_hash": "494564c8a001bce88c6cf3e5c16759210b0516459d7d4c23619b1130504d5401",
373
+ "baseline_yaml_content_hash": "352884bfbba30a002a2e79028f2abacfbd751ba35198cccde6104a75cb4e9350"
374
+ },
375
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_complex_link_history": {
376
+ "baseline_code_signature_text": "def create_complex_link_history(engine: Engine) -> Engine:",
377
+ "baseline_code_structure_hash": "9b3bf012779979584d371aa9e851f4880c5e330650aae5e1981bf4ed570fbf0d",
378
+ "baseline_yaml_content_hash": "2b18d49fe70c484ef9eb7e30b82ef7947626997888fc200007e9bc82bbb52049"
379
+ },
380
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_dirty_workspace_history": {
381
+ "baseline_code_signature_text": "def create_dirty_workspace_history(engine: Engine) -> Tuple[Engine, str]:",
382
+ "baseline_code_structure_hash": "9a1b473936bc06f3c7c301e66140295213df44abc420f8775246d5987b8c1cb0",
383
+ "baseline_yaml_content_hash": "788b7ec1efaaeb6e6b78fdfd2bdd37d2e351d623d9295291c369478832bb739d"
384
+ },
385
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_linear_history": {
386
+ "baseline_code_signature_text": "def create_linear_history(engine: Engine) -> Tuple[Engine, Dict[str, str]]:",
387
+ "baseline_code_structure_hash": "3ada516acb039d0433939843fde70504f99dee0302a1342292fc8d6c9fabf883",
388
+ "baseline_yaml_content_hash": "2b2e026a825ce169baf9da35d706d1e55fa1ca76af4b7605e78bcbc2e6383599"
389
+ },
390
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_linear_history_from_specs": {
391
+ "baseline_code_signature_text": "def create_linear_history_from_specs(engine: Engine, specs: List[Dict[str, Any]]):",
392
+ "baseline_code_structure_hash": "4e0464d5d219a29b0877daa0db5127754a0527bb0e2ce2b667521475b6913f19",
393
+ "baseline_yaml_content_hash": "c7ec7be674a17ad41caac42e79b2950813e70941b054b8b5f6b758a28b36722d"
394
+ },
395
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_node_via_cli": {
396
+ "baseline_code_signature_text": "def create_node_via_cli(runner: CliRunner, work_dir: Path, content: str) -> str:",
397
+ "baseline_code_structure_hash": "5d80af898918da29c7bf47de2fc50c82d26e55da1ed94e52cf8706bd7b84c9d8",
398
+ "baseline_yaml_content_hash": "e4aa9c4168e56c0a2f57abc6a79b10ac7853ab019b0c30b5582b0cc12dcf5577"
399
+ },
400
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_plan_node_with_change": {
401
+ "baseline_code_signature_text": "def create_plan_node_with_change(engine: Engine, parent_hash: str, file_name: str, content: str, message: str) -> str:",
402
+ "baseline_code_structure_hash": "cf61ae48f737c72cd80bbfb1fb68af0b154ff553270f31e181603b9445bc2022",
403
+ "baseline_yaml_content_hash": "8c2dc8174d13fa669d9125a57591161fa3153ad590205eeada686934077fbcb7"
404
+ },
405
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#create_query_branching_history": {
406
+ "baseline_code_signature_text": "def create_query_branching_history(engine: Engine) -> Tuple[Engine, str]:",
407
+ "baseline_code_structure_hash": "b5df830ed85fcd3b85c442eadaf3dfbe4ccc48a4f81f70f89bc0d94d02ea232e",
408
+ "baseline_yaml_content_hash": "2b33e55e9b1b15627669e69594fbb8287dac86b82599fb48aa339605fc480ac8"
409
+ },
410
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#get_local_quipu_heads": {
411
+ "baseline_code_signature_text": "def get_local_quipu_heads(work_dir: Path) -> set[str]:",
412
+ "baseline_code_structure_hash": "98f18e5a64b1643d42f06af5b609169f653f638e973dd802ce642250bd754793",
413
+ "baseline_yaml_content_hash": "568480bdd2b8aa9ef17a3754a68a6013415adf9bcf951544c00d593c28cfb1b6"
414
+ },
415
+ "py://packages/quipu-test-utils/src/pyquipu/test_utils/helpers.py#run_git_command": {
416
+ "baseline_code_signature_text": "def run_git_command(cwd: Path, args: list[str], check: bool = True) -> str:",
417
+ "baseline_code_structure_hash": "ab5208c68cb72aff451337e18f15003513c4e1c630a1f8604568417243f200d7",
418
+ "baseline_yaml_content_hash": "362d9c62b2f1936e5224993c2a2aad1fb3550f95a81f599d1f4d299e34b97b4c"
419
+ }
420
+ },
421
+ "version": "1.0"
422
+ }