페르소나 소스팩 동기화 정리
This commit is contained in:
parent
6a81ec596c
commit
e8e08935ed
10 changed files with 1126 additions and 283 deletions
108
scripts/materialize-persona-seeds.py
Normal file
108
scripts/materialize-persona-seeds.py
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
"""Materialize built-in persona seed versions on demand.
|
||||
|
||||
Default mode is a dry run: report the repository persona seed manifest without
|
||||
touching the database. Use --apply when an operator intentionally wants to run
|
||||
the existing idempotent DB materializer.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
API_ROOT = REPO_ROOT / "apps" / "api"
|
||||
if str(API_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(API_ROOT))
|
||||
|
||||
|
||||
from app.persona_repository import ( # noqa: E402
|
||||
SEED_VERSION,
|
||||
built_in_personas,
|
||||
materialize_seed_personas,
|
||||
seed_persona_id,
|
||||
)
|
||||
from app.db import close_pool, init_pool # noqa: E402
|
||||
|
||||
|
||||
def _manifest_rows() -> list[dict[str, Any]]:
|
||||
rows: list[dict[str, Any]] = []
|
||||
for card in built_in_personas():
|
||||
rows.append(
|
||||
{
|
||||
"code": card.code,
|
||||
"version": SEED_VERSION,
|
||||
"persona_id": str(seed_persona_id(card.code)),
|
||||
"display_name": card.display_name,
|
||||
"difficulty": card.difficulty,
|
||||
"theory_target": list(card.theory_target),
|
||||
"source_provenance": card.source_provenance,
|
||||
"synthetic": bool(card.is_synthetic),
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def _print_text(*, applied: bool, count: int | None, rows: list[dict[str, Any]]) -> None:
|
||||
mode = "APPLY" if applied else "DRY-RUN"
|
||||
print(f"persona seed materializer: {mode}")
|
||||
print(f"seed_version: {SEED_VERSION}")
|
||||
print(f"manifest_count: {len(rows)}")
|
||||
if count is not None:
|
||||
print(f"materialize_calls: {count}")
|
||||
for row in rows:
|
||||
theories = ",".join(row["theory_target"])
|
||||
print(
|
||||
f"- {row['code']} v{row['version']} {row['persona_id']} "
|
||||
f"{row['display_name']} [{theories}]"
|
||||
)
|
||||
|
||||
|
||||
async def _main_async(args: argparse.Namespace) -> int:
|
||||
rows = _manifest_rows()
|
||||
count: int | None = None
|
||||
if args.apply:
|
||||
await init_pool()
|
||||
try:
|
||||
count = await materialize_seed_personas()
|
||||
finally:
|
||||
await close_pool()
|
||||
payload = {
|
||||
"applied": bool(args.apply),
|
||||
"seed_version": SEED_VERSION,
|
||||
"manifest_count": len(rows),
|
||||
"materialize_calls": count,
|
||||
"personas": rows,
|
||||
}
|
||||
if args.json:
|
||||
print(json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True))
|
||||
else:
|
||||
_print_text(applied=bool(args.apply), count=count, rows=rows)
|
||||
return 0
|
||||
|
||||
|
||||
def parse_args(argv: list[str]) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Report or apply the repository persona seed/version manifest. "
|
||||
"Dry-run is the default; --apply performs DB writes through the "
|
||||
"existing idempotent materializer."
|
||||
)
|
||||
)
|
||||
parser.add_argument("--apply", action="store_true", help="write missing seed versions to DB")
|
||||
parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = parse_args(list(argv if argv is not None else sys.argv[1:]))
|
||||
return asyncio.run(_main_async(args))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue