Implement storage layer for MVP-1 Personal Tracker CLI

Add storage layer with FileStorage, MarkdownReader, and MarkdownWriter classes.
Add data models (Project, Session, Note, Change).
This commit is contained in:
2026-03-23 08:54:00 -03:00
parent 525996f60c
commit 4547c492da
16 changed files with 1013 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
"""Data models for the tracker."""
from .project import Project
from .session import Session
from .note import Note, NoteType
from .change import Change
__all__ = ["Project", "Session", "Note", "NoteType", "Change"]

13
tracker/models/change.py Normal file
View File

@@ -0,0 +1,13 @@
"""Change model definition."""
from pydantic import BaseModel, Field
from datetime import date
class Change(BaseModel):
"""Represents a notable change in a project."""
date: date
type: str # code, infra, config, docs, automation, decision
title: str
impact: str = ""
references: list[str] = Field(default_factory=list)

22
tracker/models/note.py Normal file
View File

@@ -0,0 +1,22 @@
"""Note model definition."""
from enum import Enum
from pydantic import BaseModel, Field
from datetime import datetime
class NoteType(Enum):
"""Types of notes that can be recorded during a session."""
WORK = "work"
CHANGE = "change"
BLOCKER = "blocker"
DECISION = "decision"
IDEA = "idea"
REFERENCE = "reference"
class Note(BaseModel):
"""Represents a note recorded during a session."""
type: NoteType
text: str
created_at: datetime = Field(default_factory=datetime.now)

21
tracker/models/project.py Normal file
View File

@@ -0,0 +1,21 @@
"""Project model definition."""
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Optional
class Project(BaseModel):
"""Represents a tracked project."""
id: str
name: str
slug: str
description: str = ""
type: str = "misc" # code, homelab, automation, agent, research, misc
status: str = "inbox" # inbox, next, active, blocked, waiting, done, archived
tags: list[str] = Field(default_factory=list)
root_path: str = ""
repo_path: Optional[str] = None
created_at: datetime
updated_at: datetime
last_session_at: Optional[datetime] = None

23
tracker/models/session.py Normal file
View File

@@ -0,0 +1,23 @@
"""Session model definition."""
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Optional
class Session(BaseModel):
"""Represents a work session on a project."""
id: str
project_slug: str
started_at: datetime
ended_at: Optional[datetime] = None
duration_minutes: Optional[int] = None
objective: str = ""
summary: str = ""
work_done: list[str] = Field(default_factory=list)
changes: list[str] = Field(default_factory=list)
decisions: list[str] = Field(default_factory=list)
blockers: list[str] = Field(default_factory=list)
next_steps: list[str] = Field(default_factory=list)
references: list[str] = Field(default_factory=list)
raw_notes: list[dict] = Field(default_factory=list) # [{"type": "work", "text": "...", "timestamp": "..."}]