maestro-flow 0.4.21 → 0.4.23
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.
- package/.agents/skills/maestro-analyze/SKILL.md +78 -34
- package/.agents/skills/maestro-blueprint/SKILL.md +57 -24
- package/.agents/skills/maestro-brainstorm/SKILL.md +69 -34
- package/.agents/skills/maestro-execute/SKILL.md +45 -15
- package/.agents/skills/maestro-grill/SKILL.md +63 -38
- package/.agents/skills/maestro-init/SKILL.md +59 -17
- package/.agents/skills/maestro-milestone-audit/SKILL.md +48 -5
- package/.agents/skills/maestro-milestone-complete/SKILL.md +48 -6
- package/.agents/skills/maestro-milestone-release/SKILL.md +42 -11
- package/.agents/skills/maestro-plan/SKILL.md +19 -13
- package/.agents/skills/maestro-roadmap/SKILL.md +59 -29
- package/.agents/skills/maestro-verify/SKILL.md +46 -11
- package/.agents/skills/team-adversarial-swarm/scripts/__pycache__/pheromone.cpython-313.pyc +0 -0
- package/.agents/skills/team-adversarial-swarm/scripts/__pycache__/scoring.cpython-313.pyc +0 -0
- package/.agents/skills/team-adversarial-swarm/scripts/aco.py +15 -15
- package/.agents/skills/team-adversarial-swarm/scripts/pheromone.py +2 -2
- package/.agents/skills/team-adversarial-swarm/scripts/scoring.py +1 -1
- package/.agents/skills/team-swarm/scripts/aco.py +15 -15
- package/.agents/skills/team-swarm/scripts/pheromone.py +2 -2
- package/.agents/skills/team-swarm/scripts/scoring.py +1 -1
- package/.agy/skills/maestro-analyze/SKILL.md +78 -34
- package/.agy/skills/maestro-blueprint/SKILL.md +57 -24
- package/.agy/skills/maestro-brainstorm/SKILL.md +69 -34
- package/.agy/skills/maestro-execute/SKILL.md +45 -15
- package/.agy/skills/maestro-grill/SKILL.md +63 -38
- package/.agy/skills/maestro-init/SKILL.md +59 -17
- package/.agy/skills/maestro-milestone-audit/SKILL.md +48 -5
- package/.agy/skills/maestro-milestone-complete/SKILL.md +48 -6
- package/.agy/skills/maestro-milestone-release/SKILL.md +42 -11
- package/.agy/skills/maestro-plan/SKILL.md +19 -13
- package/.agy/skills/maestro-roadmap/SKILL.md +59 -29
- package/.agy/skills/maestro-verify/SKILL.md +46 -11
- package/.agy/skills/team-adversarial-swarm/scripts/__pycache__/pheromone.cpython-313.pyc +0 -0
- package/.agy/skills/team-adversarial-swarm/scripts/__pycache__/scoring.cpython-313.pyc +0 -0
- package/.agy/skills/team-adversarial-swarm/scripts/aco.py +15 -15
- package/.agy/skills/team-adversarial-swarm/scripts/pheromone.py +2 -2
- package/.agy/skills/team-adversarial-swarm/scripts/scoring.py +1 -1
- package/.agy/skills/team-swarm/scripts/aco.py +15 -15
- package/.agy/skills/team-swarm/scripts/pheromone.py +2 -2
- package/.agy/skills/team-swarm/scripts/scoring.py +1 -1
- package/.claude/commands/maestro-analyze.md +78 -34
- package/.claude/commands/maestro-blueprint.md +57 -24
- package/.claude/commands/maestro-brainstorm.md +69 -34
- package/.claude/commands/maestro-execute.md +45 -15
- package/.claude/commands/maestro-grill.md +63 -38
- package/.claude/commands/maestro-init.md +59 -17
- package/.claude/commands/maestro-milestone-audit.md +48 -5
- package/.claude/commands/maestro-milestone-complete.md +48 -6
- package/.claude/commands/maestro-milestone-release.md +42 -11
- package/.claude/commands/maestro-plan.md +19 -13
- package/.claude/commands/maestro-roadmap.md +59 -29
- package/.claude/commands/maestro-verify.md +46 -11
- package/.claude/skills/team-adversarial-swarm/scripts/__pycache__/pheromone.cpython-313.pyc +0 -0
- package/.claude/skills/team-adversarial-swarm/scripts/__pycache__/scoring.cpython-313.pyc +0 -0
- package/.claude/skills/team-adversarial-swarm/scripts/aco.py +15 -15
- package/.claude/skills/team-adversarial-swarm/scripts/pheromone.py +2 -2
- package/.claude/skills/team-adversarial-swarm/scripts/scoring.py +1 -1
- package/.claude/skills/team-swarm/scripts/aco.py +15 -15
- package/.claude/skills/team-swarm/scripts/pheromone.py +2 -2
- package/.claude/skills/team-swarm/scripts/scoring.py +1 -1
- package/package.json +1 -1
- package/workflows/command-authoring.md +823 -0
- package/workflows/interview-mechanics.md +7 -0
|
@@ -89,7 +89,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
89
89
|
paths = SessionPaths(Path(args.session))
|
|
90
90
|
if not paths.config.exists():
|
|
91
91
|
_fail(2, f"config not found: {paths.config}")
|
|
92
|
-
config = json.loads(paths.config.read_text())
|
|
92
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
93
93
|
|
|
94
94
|
paths.ensure_dirs()
|
|
95
95
|
|
|
@@ -107,7 +107,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
107
107
|
"start_nodes": config.get("task_space", {}).get("start_nodes", "any"),
|
|
108
108
|
"edges": config.get("task_space", {}).get("edges", "complete"),
|
|
109
109
|
}
|
|
110
|
-
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False))
|
|
110
|
+
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
111
111
|
|
|
112
112
|
# Initialize pheromone
|
|
113
113
|
aco_cfg = config.get("aco", {})
|
|
@@ -148,9 +148,9 @@ def _pick_start_node(nodes: List[str], state: PheromoneState, mode: str) -> str:
|
|
|
148
148
|
|
|
149
149
|
def cmd_select(args: argparse.Namespace) -> None:
|
|
150
150
|
paths = SessionPaths(Path(args.session))
|
|
151
|
-
config = json.loads(paths.config.read_text())
|
|
151
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
152
152
|
state = PheromoneState.load(paths.pheromone_current)
|
|
153
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
153
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
154
154
|
|
|
155
155
|
n_ants = config.get("swarm", {}).get("n_ants", 5)
|
|
156
156
|
nodes = task_space["nodes"]
|
|
@@ -190,7 +190,7 @@ def _load_iteration_artifacts(paths: SessionPaths, iteration: int) -> List[dict]
|
|
|
190
190
|
artifacts = []
|
|
191
191
|
for f in files:
|
|
192
192
|
try:
|
|
193
|
-
artifacts.append(json.loads(Path(f).read_text()))
|
|
193
|
+
artifacts.append(json.loads(Path(f).read_text(encoding="utf-8")))
|
|
194
194
|
except json.JSONDecodeError as e:
|
|
195
195
|
print(f"warning: skipped malformed artifact {f}: {e}", file=sys.stderr)
|
|
196
196
|
return artifacts
|
|
@@ -213,9 +213,9 @@ def _validate_artifact(art: dict, valid_nodes: set) -> Optional[str]:
|
|
|
213
213
|
|
|
214
214
|
def cmd_update(args: argparse.Namespace) -> None:
|
|
215
215
|
paths = SessionPaths(Path(args.session))
|
|
216
|
-
config = json.loads(paths.config.read_text())
|
|
216
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
217
217
|
state = PheromoneState.load(paths.pheromone_current)
|
|
218
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
218
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
219
219
|
valid_nodes = set(task_space["nodes"])
|
|
220
220
|
|
|
221
221
|
artifacts = _load_iteration_artifacts(paths, args.iter)
|
|
@@ -266,7 +266,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
266
266
|
# Elitist: re-load best history, deposit extra on best path
|
|
267
267
|
best_data = None
|
|
268
268
|
if paths.best.exists():
|
|
269
|
-
best_data = json.loads(paths.best.read_text())
|
|
269
|
+
best_data = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
270
270
|
current_best = max(scored, key=lambda x: x["score"]) if scored else None
|
|
271
271
|
if current_best:
|
|
272
272
|
best_art = next(a for a in artifacts if a["ant_id"] == current_best["ant_id"])
|
|
@@ -281,7 +281,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
281
281
|
"evidence": best_art.get("evidence", []),
|
|
282
282
|
"updated_at": time.time(),
|
|
283
283
|
}
|
|
284
|
-
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False))
|
|
284
|
+
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
285
285
|
# Elite deposit
|
|
286
286
|
state.deposit(best_data["path"], best_data["score"])
|
|
287
287
|
|
|
@@ -292,14 +292,14 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
292
292
|
|
|
293
293
|
# Persist trails
|
|
294
294
|
trails_file = paths.trails / f"{args.iter}.jsonl"
|
|
295
|
-
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log))
|
|
295
|
+
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log), encoding="utf-8")
|
|
296
296
|
|
|
297
297
|
mean_score = sum(s["score"] for s in scored) / len(scored) if scored else 0.0
|
|
298
298
|
best_score = best_data["score"] if best_data else 0.0
|
|
299
299
|
prev_best = 0.0
|
|
300
300
|
history_files = sorted(paths.pheromone_history.glob("*.json"))
|
|
301
301
|
if len(history_files) >= 2:
|
|
302
|
-
prev = json.loads(history_files[-2].read_text())
|
|
302
|
+
prev = json.loads(history_files[-2].read_text(encoding="utf-8"))
|
|
303
303
|
prev_best = prev.get("stats", {}).get("best_known", best_score)
|
|
304
304
|
delta = best_score - prev_best
|
|
305
305
|
|
|
@@ -323,7 +323,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
323
323
|
|
|
324
324
|
def cmd_converged(args: argparse.Namespace) -> None:
|
|
325
325
|
paths = SessionPaths(Path(args.session))
|
|
326
|
-
config = json.loads(paths.config.read_text())
|
|
326
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
327
327
|
cv = config.get("convergence", {})
|
|
328
328
|
|
|
329
329
|
state = PheromoneState.load(paths.pheromone_current)
|
|
@@ -339,7 +339,7 @@ def cmd_converged(args: argparse.Namespace) -> None:
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
if paths.best.exists():
|
|
342
|
-
metrics["best_score"] = json.loads(paths.best.read_text()).get("score", 0.0)
|
|
342
|
+
metrics["best_score"] = json.loads(paths.best.read_text(encoding="utf-8")).get("score", 0.0)
|
|
343
343
|
|
|
344
344
|
# max_iterations
|
|
345
345
|
max_iter = cv.get("max_iterations", 5)
|
|
@@ -397,7 +397,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
397
397
|
|
|
398
398
|
best = None
|
|
399
399
|
if paths.best.exists():
|
|
400
|
-
best = json.loads(paths.best.read_text())
|
|
400
|
+
best = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
401
401
|
|
|
402
402
|
# Top-K trails across all iterations
|
|
403
403
|
all_trails = []
|
|
@@ -410,7 +410,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
410
410
|
# Convergence curve
|
|
411
411
|
curve = []
|
|
412
412
|
for hf in sorted(paths.pheromone_history.glob("*.json"), key=lambda p: int(p.stem)):
|
|
413
|
-
snap = json.loads(hf.read_text())
|
|
413
|
+
snap = json.loads(hf.read_text(encoding="utf-8"))
|
|
414
414
|
curve.append({
|
|
415
415
|
"iteration": snap["iteration"],
|
|
416
416
|
"entropy": snap["stats"]["entropy"],
|
|
@@ -114,11 +114,11 @@ class PheromoneState:
|
|
|
114
114
|
|
|
115
115
|
def save(self, path: Path) -> None:
|
|
116
116
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
-
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False))
|
|
117
|
+
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8")
|
|
118
118
|
|
|
119
119
|
@classmethod
|
|
120
120
|
def load(cls, path: Path) -> "PheromoneState":
|
|
121
|
-
return cls.from_dict(json.loads(path.read_text()))
|
|
121
|
+
return cls.from_dict(json.loads(path.read_text(encoding="utf-8")))
|
|
122
122
|
|
|
123
123
|
def select_neighbors(
|
|
124
124
|
self,
|
|
@@ -62,7 +62,7 @@ def load_verified_scores(scores_file: Path) -> Dict[str, float]:
|
|
|
62
62
|
"""Load pre-computed verified_scores from scorer role output (if exists)."""
|
|
63
63
|
if not scores_file.exists():
|
|
64
64
|
return {}
|
|
65
|
-
data = json.loads(scores_file.read_text())
|
|
65
|
+
data = json.loads(scores_file.read_text(encoding="utf-8"))
|
|
66
66
|
return {
|
|
67
67
|
ant_id: entry["verified_score"]
|
|
68
68
|
for ant_id, entry in data.get("scores", {}).items()
|
|
@@ -89,7 +89,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
89
89
|
paths = SessionPaths(Path(args.session))
|
|
90
90
|
if not paths.config.exists():
|
|
91
91
|
_fail(2, f"config not found: {paths.config}")
|
|
92
|
-
config = json.loads(paths.config.read_text())
|
|
92
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
93
93
|
|
|
94
94
|
paths.ensure_dirs()
|
|
95
95
|
|
|
@@ -107,7 +107,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
107
107
|
"start_nodes": config.get("task_space", {}).get("start_nodes", "any"),
|
|
108
108
|
"edges": config.get("task_space", {}).get("edges", "complete"),
|
|
109
109
|
}
|
|
110
|
-
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False))
|
|
110
|
+
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
111
111
|
|
|
112
112
|
# Initialize pheromone
|
|
113
113
|
aco_cfg = config.get("aco", {})
|
|
@@ -148,9 +148,9 @@ def _pick_start_node(nodes: List[str], state: PheromoneState, mode: str) -> str:
|
|
|
148
148
|
|
|
149
149
|
def cmd_select(args: argparse.Namespace) -> None:
|
|
150
150
|
paths = SessionPaths(Path(args.session))
|
|
151
|
-
config = json.loads(paths.config.read_text())
|
|
151
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
152
152
|
state = PheromoneState.load(paths.pheromone_current)
|
|
153
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
153
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
154
154
|
|
|
155
155
|
n_ants = config.get("swarm", {}).get("n_ants", 5)
|
|
156
156
|
nodes = task_space["nodes"]
|
|
@@ -190,7 +190,7 @@ def _load_iteration_artifacts(paths: SessionPaths, iteration: int) -> List[dict]
|
|
|
190
190
|
artifacts = []
|
|
191
191
|
for f in files:
|
|
192
192
|
try:
|
|
193
|
-
artifacts.append(json.loads(Path(f).read_text()))
|
|
193
|
+
artifacts.append(json.loads(Path(f).read_text(encoding="utf-8")))
|
|
194
194
|
except json.JSONDecodeError as e:
|
|
195
195
|
print(f"warning: skipped malformed artifact {f}: {e}", file=sys.stderr)
|
|
196
196
|
return artifacts
|
|
@@ -213,9 +213,9 @@ def _validate_artifact(art: dict, valid_nodes: set) -> Optional[str]:
|
|
|
213
213
|
|
|
214
214
|
def cmd_update(args: argparse.Namespace) -> None:
|
|
215
215
|
paths = SessionPaths(Path(args.session))
|
|
216
|
-
config = json.loads(paths.config.read_text())
|
|
216
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
217
217
|
state = PheromoneState.load(paths.pheromone_current)
|
|
218
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
218
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
219
219
|
valid_nodes = set(task_space["nodes"])
|
|
220
220
|
|
|
221
221
|
artifacts = _load_iteration_artifacts(paths, args.iter)
|
|
@@ -266,7 +266,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
266
266
|
# Elitist: re-load best history, deposit extra on best path
|
|
267
267
|
best_data = None
|
|
268
268
|
if paths.best.exists():
|
|
269
|
-
best_data = json.loads(paths.best.read_text())
|
|
269
|
+
best_data = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
270
270
|
current_best = max(scored, key=lambda x: x["score"]) if scored else None
|
|
271
271
|
if current_best:
|
|
272
272
|
best_art = next(a for a in artifacts if a["ant_id"] == current_best["ant_id"])
|
|
@@ -281,7 +281,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
281
281
|
"evidence": best_art.get("evidence", []),
|
|
282
282
|
"updated_at": time.time(),
|
|
283
283
|
}
|
|
284
|
-
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False))
|
|
284
|
+
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
285
285
|
# Elite deposit
|
|
286
286
|
state.deposit(best_data["path"], best_data["score"])
|
|
287
287
|
|
|
@@ -292,14 +292,14 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
292
292
|
|
|
293
293
|
# Persist trails
|
|
294
294
|
trails_file = paths.trails / f"{args.iter}.jsonl"
|
|
295
|
-
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log))
|
|
295
|
+
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log), encoding="utf-8")
|
|
296
296
|
|
|
297
297
|
mean_score = sum(s["score"] for s in scored) / len(scored) if scored else 0.0
|
|
298
298
|
best_score = best_data["score"] if best_data else 0.0
|
|
299
299
|
prev_best = 0.0
|
|
300
300
|
history_files = sorted(paths.pheromone_history.glob("*.json"))
|
|
301
301
|
if len(history_files) >= 2:
|
|
302
|
-
prev = json.loads(history_files[-2].read_text())
|
|
302
|
+
prev = json.loads(history_files[-2].read_text(encoding="utf-8"))
|
|
303
303
|
prev_best = prev.get("stats", {}).get("best_known", best_score)
|
|
304
304
|
delta = best_score - prev_best
|
|
305
305
|
|
|
@@ -323,7 +323,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
323
323
|
|
|
324
324
|
def cmd_converged(args: argparse.Namespace) -> None:
|
|
325
325
|
paths = SessionPaths(Path(args.session))
|
|
326
|
-
config = json.loads(paths.config.read_text())
|
|
326
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
327
327
|
cv = config.get("convergence", {})
|
|
328
328
|
|
|
329
329
|
state = PheromoneState.load(paths.pheromone_current)
|
|
@@ -339,7 +339,7 @@ def cmd_converged(args: argparse.Namespace) -> None:
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
if paths.best.exists():
|
|
342
|
-
metrics["best_score"] = json.loads(paths.best.read_text()).get("score", 0.0)
|
|
342
|
+
metrics["best_score"] = json.loads(paths.best.read_text(encoding="utf-8")).get("score", 0.0)
|
|
343
343
|
|
|
344
344
|
# max_iterations
|
|
345
345
|
max_iter = cv.get("max_iterations", 5)
|
|
@@ -397,7 +397,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
397
397
|
|
|
398
398
|
best = None
|
|
399
399
|
if paths.best.exists():
|
|
400
|
-
best = json.loads(paths.best.read_text())
|
|
400
|
+
best = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
401
401
|
|
|
402
402
|
# Top-K trails across all iterations
|
|
403
403
|
all_trails = []
|
|
@@ -410,7 +410,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
410
410
|
# Convergence curve
|
|
411
411
|
curve = []
|
|
412
412
|
for hf in sorted(paths.pheromone_history.glob("*.json"), key=lambda p: int(p.stem)):
|
|
413
|
-
snap = json.loads(hf.read_text())
|
|
413
|
+
snap = json.loads(hf.read_text(encoding="utf-8"))
|
|
414
414
|
curve.append({
|
|
415
415
|
"iteration": snap["iteration"],
|
|
416
416
|
"entropy": snap["stats"]["entropy"],
|
|
@@ -114,11 +114,11 @@ class PheromoneState:
|
|
|
114
114
|
|
|
115
115
|
def save(self, path: Path) -> None:
|
|
116
116
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
-
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False))
|
|
117
|
+
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8")
|
|
118
118
|
|
|
119
119
|
@classmethod
|
|
120
120
|
def load(cls, path: Path) -> "PheromoneState":
|
|
121
|
-
return cls.from_dict(json.loads(path.read_text()))
|
|
121
|
+
return cls.from_dict(json.loads(path.read_text(encoding="utf-8")))
|
|
122
122
|
|
|
123
123
|
def select_neighbors(
|
|
124
124
|
self,
|
|
@@ -62,7 +62,7 @@ def load_verified_scores(scores_file: Path) -> Dict[str, float]:
|
|
|
62
62
|
"""Load pre-computed verified_scores from scorer role output (if exists)."""
|
|
63
63
|
if not scores_file.exists():
|
|
64
64
|
return {}
|
|
65
|
-
data = json.loads(scores_file.read_text())
|
|
65
|
+
data = json.loads(scores_file.read_text(encoding="utf-8"))
|
|
66
66
|
return {
|
|
67
67
|
ant_id: entry["verified_score"]
|
|
68
68
|
for ant_id, entry in data.get("scores", {}).items()
|