feat(principles): retroactive cull (Phase C) + source-derived terminology (Phase D, #152)
Phase C — scripts/cull_principles.py: re-adjudicates every existing 'original' principle with the SAME panel regime (panel_keep_score → classify → apply_cap), reversible (CSV backup + rejected canonical recoverable), usage-throttled. panel_extraction.panel_keep_score + apply_cap (shared, G2). Dry-run on 3 decisions: 37→15 survive. Phase D — services/principles.py: source-derived label הלכה (binding court) / כלל פרשני (committee) / עיקרון (persuasive); umbrella עקרונות משפטיים. Wired into canonical_halacha_get/list (principle_class+principle_label). UI string changes deferred to the Claude Design gate. spec INV-LRN7; SCRIPTS.md; 7 new tests; 428 green. Phase E needs no new code — synthesis already targets pending_synthesis, which the cull leaves only on survivors (rejected canonicals → 'rejected'). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@ import asyncpg
|
||||
from pgvector.asyncpg import register_vector
|
||||
|
||||
from legal_mcp import config
|
||||
from legal_mcp.services import court_citation, halacha_quality
|
||||
from legal_mcp.services import court_citation, halacha_quality, principles
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -6156,7 +6156,8 @@ async def get_canonical_halacha(canonical_id: "UUID") -> "dict | None":
|
||||
"SELECT ch.id::text, ch.canonical_statement, ch.rule_type, "
|
||||
" ch.practice_areas, ch.subject_tags, ch.review_status, "
|
||||
" ch.instance_count, ch.created_at, ch.updated_at, "
|
||||
" cl.case_number AS first_established_case "
|
||||
" cl.case_number AS first_established_case, "
|
||||
" cl.source_kind, cl.is_binding "
|
||||
"FROM canonical_halachot ch "
|
||||
"LEFT JOIN case_law cl ON cl.id = ch.first_established_in "
|
||||
"WHERE ch.id = $1",
|
||||
@@ -6172,10 +6173,12 @@ async def get_canonical_halacha(canonical_id: "UUID") -> "dict | None":
|
||||
"WHERE h.canonical_id = $1 ORDER BY h.instance_type, cl.case_number",
|
||||
canonical_id,
|
||||
)
|
||||
return {
|
||||
**dict(row),
|
||||
"instances": [dict(i) for i in instances],
|
||||
}
|
||||
out = dict(row)
|
||||
# #152: source-derived class + Hebrew label (הלכה / כלל פרשני / עיקרון).
|
||||
out["principle_class"] = principles.principle_class(out.get("source_kind"), out.get("is_binding"))
|
||||
out["principle_label"] = principles.label_for_class(out["principle_class"])
|
||||
out["instances"] = [dict(i) for i in instances]
|
||||
return out
|
||||
|
||||
|
||||
async def list_canonical_halachot(
|
||||
@@ -6190,24 +6193,33 @@ async def list_canonical_halachot(
|
||||
params: list = []
|
||||
idx = 1
|
||||
if practice_area:
|
||||
conditions.append(f"${ idx} = ANY(practice_areas)")
|
||||
conditions.append(f"${ idx} = ANY(ch.practice_areas)")
|
||||
params.append(practice_area)
|
||||
idx += 1
|
||||
if review_status:
|
||||
conditions.append(f"review_status = ${idx}")
|
||||
conditions.append(f"ch.review_status = ${idx}")
|
||||
params.append(review_status)
|
||||
idx += 1
|
||||
params += [limit, offset]
|
||||
rows = await pool.fetch(
|
||||
f"SELECT id::text, canonical_statement, rule_type, practice_areas, "
|
||||
f" subject_tags, review_status, instance_count, created_at, updated_at "
|
||||
f"FROM canonical_halachot "
|
||||
f"SELECT ch.id::text, ch.canonical_statement, ch.rule_type, ch.practice_areas, "
|
||||
f" ch.subject_tags, ch.review_status, ch.instance_count, "
|
||||
f" ch.created_at, ch.updated_at, cl.source_kind, cl.is_binding "
|
||||
f"FROM canonical_halachot ch "
|
||||
f"LEFT JOIN case_law cl ON cl.id = ch.first_established_in "
|
||||
f"WHERE {' AND '.join(conditions)} "
|
||||
f"ORDER BY instance_count DESC, created_at DESC "
|
||||
f"ORDER BY ch.instance_count DESC, ch.created_at DESC "
|
||||
f"LIMIT ${idx} OFFSET ${idx + 1}",
|
||||
*params,
|
||||
)
|
||||
return [dict(r) for r in rows]
|
||||
out = []
|
||||
for r in rows:
|
||||
d = dict(r)
|
||||
cls = principles.principle_class(d.pop("source_kind", None), d.pop("is_binding", None))
|
||||
d["principle_class"] = cls
|
||||
d["principle_label"] = principles.label_for_class(cls)
|
||||
out.append(d)
|
||||
return out
|
||||
|
||||
|
||||
async def update_canonical_statement(
|
||||
|
||||
Reference in New Issue
Block a user