fix(tz): timezone-aware datetimes — unblock TZ=Asia/Jerusalem (#210) #368
Reference in New Issue
Block a user
Delete Branch "worktree-agent-a29624b2a56f70804"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
מה ולמה
ההמשך-בצד-השרת ל-INV-UI9 (#210). הצד-UI (PR #367) כבר נעץ תצוגה אנושית ב-
Asia/Jerusalem. ה-PR הזה הוא הדרישה-המקדימה שמאפשרת באופן בטוח להגדירTZ=Asia/Jerusalemבקונטיינר — מימוש ה"אודיט-נלווה (לא מיושם)" המוצהר ב-docs/spec/X6-ui-api-contract.md§INV-UI9: "הגדרתTZ=Asia/Jerusalemבקונטיינר בטוחה רק אם אף לוגיקה עסקית אינה תלויה בשעון-ה-process כ-UTC."האחסון נשאר UTC (
TIMESTAMPTZ, ISO-UTC ב-API). התצוגה האנושית — ישראל, דטרמיניסטית.תיקונים
mcp-server/src/legal_mcp/services/audit.py:41—datetime.utcnow()נאיבי נכתב ל-עמודתTIMESTAMPTZ(audit_log.created_at). תחתTZ=Asia/Jerusalemהערך-הנאיבי (שעון-קיר UTC) היה מתפרש כשעון-ישראל מקומי ונשמר ~3 שעות סטייה. →datetime.now(timezone.utc)(tz-aware). הוספתtimezoneל-import.scripts/calibrate_effort.py:_ts()— חותמת-הדוח עכשיו שעון-ישראל דרךZoneInfo("Asia/Jerusalem")עם סיומת בטוחה-לשם-קובץ-IL(הסקריפט רץ על ה-host שהוא UTC). נוספה שורת-כותרת מתויגת "שעון ישראל · Asia/Jerusalem" כדי שהחותמת מול היו"ר תהיה חד-משמעית.--self-testעדיין ALL PASS.mcp-server/src/legal_mcp/services/research_md.py) — נעשו דטרמיניסטיים:update_chair_positiontimestamp (שורה 363,datetime.now(IL_TZ)) ו-parse()mtime (שורה 200,datetime.fromtimestamp(..., tz=IL_TZ)) — נכונים ללא תלות ב-TZ של ה-process.הושארו ללא נגיעה במכוון (Israel-local-day — נכונים ברגע ש-TZ מתהפך, לא-מזיקים עד אז):
date.today()ב-tools/drafting.py,services/party_claims_summary.py,services/block_writer.py(תאריך-החלטה מודפס), ו-year-cutoff ב-services/court_fetch_supreme.py— ועדה ירושלמית רוצה את היום-הקלנדרי הישראלי.Invariants — הצהרה (חובה)
צ'קליסט — פרוטוקול כתיבת-קוד
docs/spec/00-constitution.md(§6) +docs/spec/X6-ui-api-contract.md(INV-UI9) לפני הכתיבהmcp-server/srcנקיdocs/spec/gap-audit.md— לא נגעתי ב-GAP/FU ממופה--self-testALL PASS--applyאימות
mcp-server/.venv/bin/python scripts/calibrate_effort.py --self-test→ ALL PASS (14/14, EXIT=0).python -c "import ast; ..."על שלושת הקבצים → clean.PYTHONPATH=mcp-server/src python -c "import legal_mcp.server"→ OK (אין שבירת-import);import legal_mcp.services.audit+research_md→ OK._ts()מפיק20260630T202319-IL— בטוח-לשם-קובץ, חד-משמעי-ישראל;datetime.now(IL_TZ).isoformat()→+03:00.🤖 Generated with Claude Code
Backend follow-up to INV-UI9 (X6 §"אודיט-נלווה"): make server-side datetimes explicit so flipping the container to TZ=Asia/Jerusalem cannot silently skew stored or displayed timestamps. Storage stays UTC; human display is Israel time. - audit.py: naive datetime.utcnow() → datetime.now(timezone.utc) for the TIMESTAMPTZ audit_log.created_at. Under TZ=Asia/Jerusalem the naive UTC wall-clock would be read as Israel-local and stored ~3h off. (§6: no silent skew.) - calibrate_effort.py: _ts() report stamp now Israel-time via ZoneInfo("Asia/Jerusalem") with a filename-safe "-IL" suffix (script runs on the UTC host); added a labeled "שעון ישראל" line to the report header so the chair-facing timestamp is unambiguous. --self-test still ALL PASS. - research_md.py: display fields made deterministic Israel-tz — update_chair_position timestamp (datetime.now(IL_TZ)) and parse() mtime (datetime.fromtimestamp(..., tz=IL_TZ)) — correct regardless of process TZ. Left intentionally Israel-local-day date.today()/year-cutoff call sites untouched (drafting/party_claims_summary/block_writer/court_fetch_supreme) — a Jerusalem committee wants the Israel calendar day; they resolve correctly once TZ flips. Invariants: INV-UI9 (store-UTC / display-Israel, server side); §6 (timezone-aware datetimes, no silent ~3h skew). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>