Skip to content

donna.capabilities.weekly_review_skill

donna.capabilities.weekly_review_skill

Slice 16 — weekly self-review scaffold.

Fires Sunday evening (UTC, configurable) via :class:AsyncCronScheduler. Writes WeeklyReview/{iso_year}-W{iso_week:02d}.md summarising the week's meetings, completed tasks, logged commitments, and chat highlights.

Idempotency: the ISO week string (e.g. "2026-W17"). Re-runs within the same week short-circuit inside :class:MemoryInformedWriter.

logger module-attribute

logger = get_logger()

WeeklyReviewSkill

WeeklyReviewSkill(*, writer: MemoryInformedWriter, memory_store: MemoryStore, vault_client: VaultClient, connection: Connection, config: WeeklyReviewSkillConfig, user_id: str)

Compose a week's worth of memory context and delegate to the writer.

Source code in src/donna/capabilities/weekly_review_skill.py
def __init__(
    self,
    *,
    writer: MemoryInformedWriter,
    memory_store: MemoryStore,
    vault_client: VaultClient,
    connection: aiosqlite.Connection,
    config: WeeklyReviewSkillConfig,
    user_id: str,
) -> None:
    self._writer = writer
    self._memory_store = memory_store
    self._vault_client = vault_client
    self._conn = connection
    self._config = config
    self._user_id = user_id

TEMPLATE class-attribute instance-attribute

TEMPLATE = 'weekly_review.md.j2'

TASK_TYPE class-attribute instance-attribute

TASK_TYPE = 'draft_weekly_review'

run_for_week async

run_for_week(week_start: date) -> WriteResult
Source code in src/donna/capabilities/weekly_review_skill.py
async def run_for_week(self, week_start: date) -> WriteResult:
    week_start = _week_start_for(week_start)
    _, iso_week = _iso_week_range(week_start)
    target_path = f"WeeklyReview/{iso_week}.md"

    async def context_gather() -> dict[str, Any]:
        return await self._gather_context(week_start)

    logger.info(
        "weekly_review_triggered",
        iso_week=iso_week,
        user_id=self._user_id,
    )
    return await self._writer.run(
        template=self.TEMPLATE,
        task_type=self.TASK_TYPE,
        context_gather=context_gather,
        target_path=target_path,
        idempotency_key=iso_week,
        user_id=self._user_id,
        autonomy_level=self._config.autonomy_level,
    )