|
11 | 11 | import subprocess |
12 | 12 | import sys |
13 | 13 | import tempfile |
| 14 | +from typing import Any |
14 | 15 |
|
15 | 16 | from loopx.bootstrap import bootstrap_project |
16 | 17 | from loopx.configure_goal import configure_goal |
|
23 | 24 | REGISTRY_NAME = "registry.json" |
24 | 25 |
|
25 | 26 |
|
26 | | -def checked(result: dict) -> dict: |
| 27 | +def checked(result: dict[str, Any]) -> dict[str, Any]: |
27 | 28 | if not result.get("ok"): |
28 | 29 | raise RuntimeError(json.dumps(result, ensure_ascii=False)) |
29 | 30 | return result |
30 | 31 |
|
31 | 32 |
|
32 | | -def write_story_artifacts(project: Path, story: dict, notice: str) -> None: |
| 33 | +def write_story_artifacts(project: Path, story: dict[str, Any], notice: str) -> None: |
33 | 34 | (project / "BRIEF.md").write_text(f"# {story['title']}\n\n{story['brief']}\n") |
34 | 35 | with (project / "working-table.csv").open("w", newline="") as table: |
35 | 36 | writer = csv.writer(table) |
@@ -68,9 +69,10 @@ def write_story_artifacts(project: Path, story: dict, notice: str) -> None: |
68 | 69 | ) |
69 | 70 |
|
70 | 71 |
|
71 | | -def seed_delivery_tasks(story: dict, registry: Path, runtime: Path) -> list: |
| 72 | +def seed_delivery_tasks(story: dict[str, Any], registry: Path, runtime: Path) -> list[dict[str, Any]]: |
72 | 73 | """Record each story dependency as the typed relation its state allows.""" |
73 | | - todos, ids = [], {} |
| 74 | + todos: list[dict[str, Any]] = [] |
| 75 | + ids: dict[str, str] = {} |
74 | 76 | by_key = {task["key"]: task for task in story["tasks"]} |
75 | 77 | dependents: dict[str, list[str]] = {} |
76 | 78 | for task in story["tasks"]: |
@@ -132,7 +134,7 @@ def seed_delivery_tasks(story: dict, registry: Path, runtime: Path) -> list: |
132 | 134 | return todos |
133 | 135 |
|
134 | 136 |
|
135 | | -def seed_story(root: Path, story: dict, notice: str) -> dict: |
| 137 | +def seed_story(root: Path, story: dict[str, Any], notice: str) -> dict[str, Any]: |
136 | 138 | runtime = root / "runtime" |
137 | 139 | registry = root / REGISTRY_NAME |
138 | 140 | project = root / "projects" / story["id"] |
@@ -263,14 +265,14 @@ def seed_story(root: Path, story: dict, notice: str) -> dict: |
263 | 265 | } |
264 | 266 |
|
265 | 267 |
|
266 | | -def prepare(root: Path) -> dict: |
| 268 | +def prepare(root: Path) -> dict[str, Any]: |
267 | 269 | root = root.expanduser() |
268 | 270 | if root.is_symlink(): |
269 | 271 | raise ValueError("Demo root must not be a symlink") |
270 | 272 | root = root.resolve() |
271 | 273 | marker = root / MARKER |
272 | 274 | if marker.exists(): |
273 | | - manifest = json.loads(marker.read_text()) |
| 275 | + manifest: dict[str, Any] = json.loads(marker.read_text()) |
274 | 276 | if manifest.get("schema_version") != "workspace_story_demo_v3": |
275 | 277 | raise ValueError("Unrecognized demo manifest") |
276 | 278 | if manifest.get("root") != str(root) or manifest.get("registry") != str( |
@@ -302,7 +304,7 @@ def prepare(root: Path) -> dict: |
302 | 304 |
|
303 | 305 |
|
304 | 306 | def advance( |
305 | | - root: Path, manifest: dict, story_id: str, decision_key: str | None |
| 307 | + root: Path, manifest: dict[str, Any], story_id: str, decision_key: str | None |
306 | 308 | ) -> None: |
307 | 309 | story = next(s for s in manifest["goals"] if s["id"] == story_id) |
308 | 310 | registry = root / REGISTRY_NAME |
|
0 commit comments