mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-15 03:50:57 +01:00
Project.kind (focus default; old rows load unchanged) plus interview fields test_at, invite_url, trips, weekend_answers. Interview budget 30 min weekdays / 120 Sat-Sun, exempt from daily_floor, unlock clamped after the 0.7.0 history ratchet. Milestones are generated (rules, trip_ask, phone, mock, slot), never stored. Append-only evidence store behind the _paths seam. Calendar dropped: slot = slot entry + slot_confirm. Failure paths: - unanswered trip question: fail closed (reads as a trip, phone due) - late no-trip answer cannot erase an overdue phone milestone: closed - phone source missing/stale/crashed: unknown, locks: fail closed - trip_ask answer: evidence row first, then registry; a crash between leaves the question open: fail closed - add_trip/answer_weekend loosening: ValueError, nothing written - owed_lock with unreadable registry or evidence: fail open, logged (focus-guard's unreadable-registry rule); test day never locks - status() milestones with unreadable evidence: empty list, logged - torn or non-utf8 evidence lines: skipped and logged Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWZUTC9Zzdzsx7VW7dm
48 lines
1.2 KiB
Python
48 lines
1.2 KiB
Python
# Copyright (c) 2026 Krzysztof Rudnicki
|
|
"""Where the data lives, resolved on every call so tests can redirect it."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
ENV_VAR = "FOCUS_PROJECT_DATA"
|
|
|
|
|
|
def data_dir() -> Path:
|
|
"""``$FOCUS_PROJECT_DATA`` or ``~/.local/share/focus_project``."""
|
|
override = os.environ.get(ENV_VAR)
|
|
if override:
|
|
return Path(override)
|
|
return Path.home() / ".local" / "share" / "focus_project"
|
|
|
|
|
|
def projects_path() -> Path:
|
|
"""The registry file; this package is its only writer."""
|
|
return data_dir() / "projects.json"
|
|
|
|
|
|
def activity_path() -> Path:
|
|
"""The append-only activity log."""
|
|
return data_dir() / "activity.jsonl"
|
|
|
|
|
|
def lock_path() -> Path:
|
|
"""The registry's writer lock."""
|
|
return data_dir() / "projects.lock"
|
|
|
|
|
|
def evidence_dir() -> Path:
|
|
"""Interview-prep evidence: one jsonl per project plus copied files."""
|
|
return data_dir() / "evidence"
|
|
|
|
|
|
def evidence_path(project_id: str) -> Path:
|
|
"""The append-only evidence rows of one project."""
|
|
return evidence_dir() / f"{project_id}.jsonl"
|
|
|
|
|
|
def evidence_files_dir(project_id: str) -> Path:
|
|
"""Where evidence files (screenshots) of one project are copied."""
|
|
return evidence_dir() / project_id
|