Add docs, scripts, skills, commands, and taskmaster config to repo
Includes: - docs/: architecture, block-schema, migration-plan, product-specification - scripts/: bidi_table, decompose-decisions, extract-claims, seed-knowledge, etc. - skill-legal-decision/: SKILL.md + references + block-schema - skill-legal-assistant/: SKILL.md - skill-legal-docx/: SKILL.md + references - .claude/commands/: bidi-table skill - .taskmaster/: task config + PRDs - .gitignore: exclude legacy/, kiryat-yearim/, node_modules/, memory/ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
139
scripts/export-decision-docx.py
Normal file
139
scripts/export-decision-docx.py
Normal file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Export a decision from DB to DOCX using the CJS template generator.
|
||||
|
||||
Usage: python export-decision-docx.py <case_number> [output.docx]
|
||||
|
||||
Pulls decision blocks from DB, generates structure JSON,
|
||||
invokes create-decision-structure.cjs to produce DOCX.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent / "mcp-server" / "src"))
|
||||
|
||||
from legal_mcp.services.db import get_pool, init_schema, close_pool
|
||||
|
||||
CJS_SCRIPT = Path(__file__).parent.parent / "skill-legal-decision" / "scripts" / "create-decision-structure.cjs"
|
||||
|
||||
|
||||
def block_id_to_hebrew(block_id: str) -> str:
|
||||
"""Map block_id to Hebrew letter label."""
|
||||
mapping = {
|
||||
"block-alef": "א", "block-bet": "ב", "block-gimel": "ג",
|
||||
"block-dalet": "ד", "block-he": "ה", "block-vav": "ו",
|
||||
"block-zayin": "ז", "block-chet": "ח", "block-tet": "ט",
|
||||
"block-yod": "י", "block-yod-alef": "יא", "block-yod-bet": "יב",
|
||||
}
|
||||
return mapping.get(block_id, "")
|
||||
|
||||
|
||||
async def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("שימוש: python export-decision-docx.py <מספר_תיק> [output.docx]")
|
||||
sys.exit(1)
|
||||
|
||||
case_number = sys.argv[1]
|
||||
output_path = sys.argv[2] if len(sys.argv) > 2 else f"החלטה-{case_number}.docx"
|
||||
|
||||
await init_schema()
|
||||
pool = await get_pool()
|
||||
|
||||
async with pool.acquire() as conn:
|
||||
# Get case info
|
||||
case = await conn.fetchrow(
|
||||
"SELECT * FROM cases WHERE case_number = $1", case_number
|
||||
)
|
||||
if not case:
|
||||
print(f"תיק {case_number} לא נמצא")
|
||||
sys.exit(1)
|
||||
|
||||
# Get decision
|
||||
decision = await conn.fetchrow(
|
||||
"SELECT * FROM decisions WHERE case_id = $1 AND status = 'final'",
|
||||
case["id"],
|
||||
)
|
||||
if not decision:
|
||||
print(f"אין החלטה סופית לתיק {case_number}")
|
||||
sys.exit(1)
|
||||
|
||||
# Get blocks
|
||||
blocks = await conn.fetch(
|
||||
"""SELECT block_id, block_index, title, content, word_count
|
||||
FROM decision_blocks
|
||||
WHERE decision_id = $1
|
||||
ORDER BY block_index""",
|
||||
decision["id"],
|
||||
)
|
||||
|
||||
await close_pool()
|
||||
|
||||
# Build structure JSON for CJS script
|
||||
appellants = json.loads(case["appellants"]) if isinstance(case["appellants"], str) else case["appellants"]
|
||||
respondents = json.loads(case["respondents"]) if isinstance(case["respondents"], str) else case["respondents"]
|
||||
|
||||
structure = {
|
||||
"metadata": {
|
||||
"case_number": case["case_number"],
|
||||
"title": case["title"],
|
||||
"subject": case["subject"],
|
||||
"property_address": case["property_address"],
|
||||
"committee": case["committee_type"],
|
||||
"outcome": decision["outcome"] or "",
|
||||
"decision_date": str(decision["decision_date"]) if decision["decision_date"] else "",
|
||||
"author": decision["author"],
|
||||
},
|
||||
"parties": {
|
||||
"appellants": [{"name": a} for a in appellants],
|
||||
"respondents": [{"name": r} for r in respondents],
|
||||
},
|
||||
"blocks": [],
|
||||
}
|
||||
|
||||
for block in blocks:
|
||||
content = block["content"] or ""
|
||||
# Skip empty header blocks
|
||||
if block["block_id"] in ("block-alef", "block-bet", "block-gimel", "block-dalet") and not content:
|
||||
continue
|
||||
|
||||
paragraphs = [p.strip() for p in content.split("\n") if p.strip()]
|
||||
|
||||
structure["blocks"].append({
|
||||
"id": block["block_id"],
|
||||
"index": block["block_index"],
|
||||
"title": block["title"],
|
||||
"hebrew_letter": block_id_to_hebrew(block["block_id"]),
|
||||
"word_count": block["word_count"],
|
||||
"paragraphs": paragraphs,
|
||||
})
|
||||
|
||||
# Write JSON (absolute paths)
|
||||
output_abs = Path(output_path).resolve()
|
||||
json_path = output_abs.with_suffix(".json")
|
||||
json_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(json_path, "w", encoding="utf-8") as f:
|
||||
json.dump(structure, f, ensure_ascii=False, indent=2)
|
||||
print(f"JSON נוצר: {json_path}")
|
||||
|
||||
# Run CJS script with absolute paths
|
||||
result = subprocess.run(
|
||||
["node", str(CJS_SCRIPT), str(json_path), str(output_abs)],
|
||||
capture_output=True, text=True,
|
||||
cwd=str(CJS_SCRIPT.parent),
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
print(f"✅ DOCX נוצר: {output_path}")
|
||||
else:
|
||||
print(f"❌ שגיאה ביצירת DOCX:")
|
||||
print(result.stderr)
|
||||
# JSON is still available for manual processing
|
||||
print(f"ה-JSON זמין: {json_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user