From 4fd442edc55e5492c8b185230418e1719a2c6fb1 Mon Sep 17 00:00:00 2001 From: archae0pteryx Date: Mon, 4 May 2026 21:38:46 -0700 Subject: [PATCH] docs: changelog + context for in-flight 033/034/035 + issue queue status - CHANGELOG: Unreleased entries for PRs #39 (033), #40 (034), #41 (035), #42 (cleanup), and the Taskfile ralph-include fix - CONTEXT: add TaskText and DomainError to the ubiquitous language - issues/README: mark 033/034/035 as in-flight (PR open) --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ CONTEXT.md | 8 ++++++++ issues/README.md | 6 +++--- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 580277f..93b3c45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,40 @@ All notable changes to adhd-ranch. Follows [Keep a Changelog](https://keepachang ## [Unreleased] +### Added — 034 focus/task invariants in domain (PR #40, in flight) + +- `crates/domain/src/error.rs` — new `DomainError` enum: `EmptyTitle`, `EmptyTaskText` +- `NewFocus::new(title, description) -> Result` validated constructor +- `crates/domain/src/focus.rs` — `TaskText` newtype with validated `new` + `as_str` +- `From for CommandError` — maps to `BadRequest` +- Command-handler regression tests assert blank input → `BadRequest` + +### Changed — 034 + +- `Commands::create_focus` and `Commands::append_task` no longer carry their own `trim().is_empty()` guards; they call `NewFocus::new` and `TaskText::new` instead +- Focus title and task text invariants now enforced once in `crates/domain/` + +### Added — 035 unit tests for `MarkdownFocusStore` (PR #41, in flight) + +- 8 direct unit tests in `crates/storage/src/focus_store.rs`: create/list roundtrip, timer sidecar present/absent, delete + delete-of-unknown, corrupted `timer.json`, append/delete task persistence +- Storage seam now independently trusted without going through `Commands` + +### Changed — 035 + +- `MarkdownFocusStore::list()` degrades to `timer: None` when `timer.json` is corrupted instead of failing the whole load — UI keeps showing the focus, user can recreate the timer + +### Changed — 033 pig/drag IPC moved into `api/` layer (PR #39, in flight) + +- `src/api/pig.ts` — new typed wrappers: `setPigDragActive`, `updatePigRects`, `subscribeGatherPigs`, `subscribeDisplayRegion` +- `src/types/pig.ts` — shared `SpawnRegion`, `PigHitRect` (api/ no longer depends on hooks/) +- `src/components/App.tsx` and `src/hooks/usePigMovement.ts` no longer import `@tauri-apps/api/core` or `@tauri-apps/api/event`; both go through `src/api/pig.ts` +- Subscription effects wrap a no-op fallback so cleanup cannot raise an unhandled rejection on strict-mode unmount + +### Fixed + +- `Taskfile.yaml` — drop stale `ralph/` include (left dangling by `dabed05 remove ralph dir`); `task check` runs again +- `issues/` — archive pre-merge drafts of 013/016/018/019/020 and move 032 into `issues/done/` (PR #42) + ### Added — 028 focus timer: domain types + full-stack creation (PR #32) - `crates/domain/src/timer.rs` — pure domain: `FocusTimer`, `TimerPreset` (2/4/8/16/32m + Custom), `TimerStatus`, `timer_remaining_secs()`, `growth_factor()` diff --git a/CONTEXT.md b/CONTEXT.md index 7b2ea3d..af4e179 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -30,6 +30,14 @@ An optional countdown attached to a Focus at creation time. Stores `duration_sec A named duration choice offered at Focus creation: 2m, 4m, 8m, 16m, 32m, or Custom (free integer minutes). Maps to `duration_secs` in `FocusTimer`. +### TaskText + +Newtype wrapper around a non-empty `String`. Construct via `TaskText::new(text)` — returns `DomainError::EmptyTaskText` for blank input. The only way `Commands::append_task` passes text into the storage layer. + +### DomainError + +Errors raised by validated domain constructors (`NewFocus::new`, `TaskText::new`). Variants: `EmptyTitle`, `EmptyTaskText`. Maps to `CommandError::BadRequest` at the commands layer. Domain owns the invariants; the commands layer owns the protocol mapping. + ## Persistence Focus = a self-contained directory under `~/.adhd-ranch/focuses//`: diff --git a/issues/README.md b/issues/README.md index 04a0368..a0e7b71 100644 --- a/issues/README.md +++ b/issues/README.md @@ -6,9 +6,9 @@ Each issue is a self-contained vertical slice an AFK coding agent ("ralph") can Complete these before picking up any other open issue. All are unblocked and independent — grab any order. -- [ ] [033 — Extract pig/drag IPC into api/ layer](033-pig-ipc-api-layer.md) -- [ ] [034 — Move Focus/Task invariants into domain](034-focus-invariants-in-domain.md) -- [ ] [035 — Unit tests for MarkdownFocusStore](035-focus-store-unit-tests.md) +- [~] [033 — Extract pig/drag IPC into api/ layer](033-pig-ipc-api-layer.md) — PR #39 open, awaiting review +- [~] [034 — Move Focus/Task invariants into domain](034-focus-invariants-in-domain.md) — PR #40 open, awaiting review +- [~] [035 — Unit tests for MarkdownFocusStore](035-focus-store-unit-tests.md) — PR #41 open, awaiting review - [ ] [036 — Generate TypeScript types from Rust via ts-rs](036-ts-types-from-rust.md) ## How to pick up an issue