전 저장소 리팩터링과 SSOT 정비

This commit is contained in:
Yun Chan 2026-07-15 21:31:30 +09:00
parent 14ecbd4e7d
commit 3dfddcac6f
173 changed files with 19679 additions and 6952 deletions

View file

@ -117,7 +117,9 @@ def load_file_personas(persona_dir: Path = REPO_PERSONA_DIR) -> list[PersonaCard
def built_in_personas() -> list[PersonaCard]:
"""Return deterministic built-in catalog cards from code seeds plus repo JSON cards."""
cards: dict[str, PersonaCard] = {card.code.upper(): card for card in SEED_PERSONAS.values()}
cards: dict[str, PersonaCard] = {
card.code.upper(): card for card in SEED_PERSONAS.values()
}
for card in load_file_personas():
cards.setdefault(card.code.upper(), card)
return [cards[code] for code in sorted(cards)]
@ -222,7 +224,14 @@ def seed_fallback_persona(code: str) -> CatalogPersona | None:
normalized = code.strip().upper()
card = get_seed_persona(normalized)
if card is None:
card = next((entry for entry in load_file_personas() if entry.code.upper() == normalized), None)
card = next(
(
entry
for entry in load_file_personas()
if entry.code.upper() == normalized
),
None,
)
if card is None:
return None
return CatalogPersona(
@ -448,6 +457,83 @@ async def get_persona_draft_record(
return persona_draft_record_from_row(row) if row is not None else None
async def _insert_persona_card(
conn: Any,
*,
persona_id: str,
card: PersonaCard,
version: int,
next_status: str,
author_id: str,
returning_columns: str,
) -> Any:
"""Insert one immutable persona version from the canonical PersonaCard shape."""
return await conn.fetchrow(
f"""
INSERT INTO app.persona_card (
persona_id, code, version, status, display_name, difficulty,
theory_target, demographics, presenting, history, big5,
resistance, speech_style, affect_baseline, ccd,
dsm5_dimensional, source_provenance, is_synthetic, triggers,
created_by
)
VALUES (
$1::uuid, $2, $3, $4, $5, $6,
$7::text[], $8::jsonb, $9::jsonb, $10::jsonb, $11::jsonb,
$12::jsonb, $13::jsonb, $14::jsonb, $15::jsonb,
$16::jsonb, $17, $18, $19::jsonb, $20::uuid
)
RETURNING {returning_columns}
""",
persona_id,
card.code,
version,
next_status,
card.display_name,
card.difficulty,
card.theory_target,
card.demographics,
card.presenting,
card.history,
card.big5,
card.resistance,
card.speech_style,
card.affect_baseline,
card.ccd,
card.dsm5_dimensional,
card.source_provenance,
card.is_synthetic,
card.triggers,
author_id,
)
async def _record_persona_create_audit(
conn: Any,
*,
author_id: str,
action: str,
persona_id: str,
next_status: str,
card: PersonaCard,
version: int,
) -> None:
await conn.execute(
"""
INSERT INTO audit.audit_log (
actor_uid, action, target_kind, target_id, detail
)
VALUES ($1::uuid, $2, $3, $4, $5::jsonb)
""",
author_id,
action,
"persona_card",
persona_id,
{"next_status": next_status, "code": card.code, "version": version},
)
async def create_persona_draft(
*,
card: PersonaCard,
@ -470,60 +556,23 @@ async def create_persona_draft(
""",
card.code,
)
row = await conn.fetchrow(
f"""
INSERT INTO app.persona_card (
persona_id, code, version, status, display_name, difficulty,
theory_target, demographics, presenting, history, big5,
resistance, speech_style, affect_baseline, ccd,
dsm5_dimensional, source_provenance, is_synthetic, triggers,
created_by
)
VALUES (
$1::uuid, $2, $3, $4, $5, $6,
$7::text[], $8::jsonb, $9::jsonb, $10::jsonb, $11::jsonb,
$12::jsonb, $13::jsonb, $14::jsonb, $15::jsonb,
$16::jsonb, $17, $18, $19::jsonb, $20::uuid
)
RETURNING {_REVIEW_COLUMNS}
""",
persona_id,
card.code,
int(version or 1),
next_status,
card.display_name,
card.difficulty,
card.theory_target,
card.demographics,
card.presenting,
card.history,
card.big5,
card.resistance,
card.speech_style,
card.affect_baseline,
card.ccd,
card.dsm5_dimensional,
card.source_provenance,
card.is_synthetic,
card.triggers,
author_id,
row = await _insert_persona_card(
conn,
persona_id=persona_id,
card=card,
version=int(version or 1),
next_status=next_status,
author_id=author_id,
returning_columns=_REVIEW_COLUMNS,
)
await conn.execute(
"""
INSERT INTO audit.audit_log (
actor_uid, action, target_kind, target_id, detail
)
VALUES ($1::uuid, $2, $3, $4, $5::jsonb)
""",
author_id,
"persona_draft_create",
"persona_card",
persona_id,
{
"next_status": next_status,
"code": card.code,
"version": int(row["version"]),
},
await _record_persona_create_audit(
conn,
author_id=author_id,
action="persona_draft_create",
persona_id=persona_id,
next_status=next_status,
card=card,
version=int(row["version"]),
)
return persona_review_item_from_row(row)
@ -577,60 +626,23 @@ async def create_persona_revision_from_existing(
""",
card.code,
)
row = await conn.fetchrow(
f"""
INSERT INTO app.persona_card (
persona_id, code, version, status, display_name, difficulty,
theory_target, demographics, presenting, history, big5,
resistance, speech_style, affect_baseline, ccd,
dsm5_dimensional, source_provenance, is_synthetic, triggers,
created_by
)
VALUES (
$1::uuid, $2, $3, $4, $5, $6,
$7::text[], $8::jsonb, $9::jsonb, $10::jsonb, $11::jsonb,
$12::jsonb, $13::jsonb, $14::jsonb, $15::jsonb,
$16::jsonb, $17, $18, $19::jsonb, $20::uuid
)
RETURNING {_CARD_COLUMNS}, created_at, approved_at
""",
persona_id,
card.code,
int(version or 1),
next_status,
card.display_name,
card.difficulty,
card.theory_target,
card.demographics,
card.presenting,
card.history,
card.big5,
card.resistance,
card.speech_style,
card.affect_baseline,
card.ccd,
card.dsm5_dimensional,
card.source_provenance,
card.is_synthetic,
card.triggers,
author_id,
row = await _insert_persona_card(
conn,
persona_id=persona_id,
card=card,
version=int(version or 1),
next_status=next_status,
author_id=author_id,
returning_columns=f"{_CARD_COLUMNS}, created_at, approved_at",
)
await conn.execute(
"""
INSERT INTO audit.audit_log (
actor_uid, action, target_kind, target_id, detail
)
VALUES ($1::uuid, $2, $3, $4, $5::jsonb)
""",
author_id,
"persona_revision_create",
"persona_card",
persona_id,
{
"next_status": next_status,
"code": card.code,
"version": int(row["version"]),
},
await _record_persona_create_audit(
conn,
author_id=author_id,
action="persona_revision_create",
persona_id=persona_id,
next_status=next_status,
card=card,
version=int(row["version"]),
)
return persona_draft_record_from_row(row)