# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Versioning Policy This project follows Semantic Versioning (SemVer). Breaking changes (removed tools, changed parameters) increment the major version. ## [1.4.4] – 2026-04-20 ### Updated - **README.md restructuring** — consolidated `get_activities` and `like_post` into Wall & Activities section - `get_activities` moved from Lists & Tasks to Wall & Activities (belongs with wall functionality) - `like_post` reference removed from Lists & Tasks (consolidated in one section) - Version bump in README header: v1.3.1 → v1.4.3 ### Notes - Documentation-only release; no code changes - All tools remain functional and unchanged - Improves UX by grouping related wall/activity tools in one section ## [1.4.3] – 2026-04-18 ### Improved - **Usability: ID resolution in docstrings** — enforce transparent display of human-readable names: - `get_tasks`: Document required member/category name resolution before user display - `get_lists`: Document required circle name resolution before user display - `get_activities`: Document required author name resolution before user display - `get_wall_posts`: Document required author name resolution before user display - `get_members`: Added proactive call guidance before presenting member-ID data - `get_circles`: Added proactive call guidance before presenting circle-ID data - `get_categories`: Added proactive call guidance for shopping list tasks - `get_meal_plan`: Document required recipe name resolution for recipe_id before user display - `CLAUDE.md`: Added general usability rule at top of implementation section ### Notes - No breaking changes; docstring enhancements only - All tools remain backward compatible - Ensures consistent UX: no raw numeric/metaIDs shown to users in any context ## [1.4.2] – 2026-04-18 ### Fixed - **`get_tasks` support for secondary circles** — lists in non-primary circles now return tasks correctly - Circle is automatically derived from `list_id` format (`taskList/_`) - Scope parameter passed to `accgetallfamily` call; matches `get_lists` pattern - Docstring updated to clarify circle support and list_id format requirement ### Notes - `_accgetallfamily()` now accepts optional `scope` parameter for secondary circle support - No breaking changes; all existing code remains compatible ## [1.4.1] – 2026-04-17 ### Improved - **Docstring enhancements** — clearer tool usage guidance for new Claude sessions: - `get_wall_posts`: Added note that results include automatic activity entries (task updates, list changes) - `get_activities`: Expanded description and added distinction from `get_wall_posts` - `like_post`: Extended post_id examples to include `task/` and `taskList/` IDs from activities - `get_recipe_categories`: Added usage notes (IDs for create/update, 5 free-tier categories, family-wide scope) - `add_meal_note`: Clarified create-only behavior; to update, delete then recreate - `clear_list`: Moved risk warning (default deletes all tasks) to opening line for visibility - `create_recipe`: Verified IMPORTANT confirmation line present ### Notes - No breaking changes; docstring improvements only - All tools remain backward compatible ## [1.4.0] – 2026-04-17 ### Added - **Unit test suite** (`tests/test_unit.py`) — comprehensive tests for core modules - `fw_client.py`: Error handling (top-level `ex`/`un`, nested `a00.un.un`/`a00.ex.ex`, successful responses) - `recipes.py`: `ingredients_parsed` parser (newline handling, empty lines, headings, commas) - `lists.py`: System list name translation (SYS-CAT-SHOPPINGLIST, SYS-CAT-TODOS, unknown names) - `server.py`: `_validate_date()` (ISO YYYY-MM-DD validation, format errors) - `server.py`: `_err()` helper (JSON response format, Unicode, special characters) - All tests use `unittest.mock` (stdlib, no external dependencies) - Tests run without API access; all HTTP calls are mocked - Framework: pytest with asyncio support ### Notes - Run tests: `uv run pytest tests/test_unit.py -v` - No breaking changes; release is testing infrastructure only ## [1.3.1] – 2026-04-17 ### Fixed - **`add_comment` response parser**: corrected response structure from `a00.r.r` with `metaId` to nested `a00.r.r.comment.commentId`; response now includes `"created": true` flag - **`add_comment` error handling**: now returns error messages directly instead of warnings ### Added - **`delete_wall_post`** — permanently delete a wall post using the `metadelete` endpoint (identical to deleting tasks and recipes) ### Notes - All wall post tools now complete CRUD operations (Create, Read, Update via like_post, Delete) - Test post (wall/16282169_31146617) removed from production after verification ## [1.3.0] – 2026-04-17 ### Added - **Wall post reading**: `get_wall_posts` — retrieve recent wall posts with author, text, creation date, like count, liked-by-me flag, and comment count - **Wall post writing**: `create_wall_post` — publish a new status post to the wall - **Comments**: `add_comment` — add a comment to a wall post or activity - All three new wall post tools require user confirmation before calling ### Notes - `get_wall_posts` supersedes the activity-listing functionality of `get_activities` (which continues to exist for backward compatibility) - `like_post` already supports both wall posts and activities; verified to work with metaIds from both `get_wall_posts` and `get_activities` - Post IDs are in the format `wall/_` ## [1.2.0] – 2026-04-17 ### Added - **Unlike support** for `like_post`: passing `like=False` now removes a STAR reaction via `add=$empty, remove.0=STAR` (array dot-notation). New optional `mood` parameter (default `"STAR"`). - **Reminder write support** for `create_task` and `update_task`: - `reminder_unit`: `"MINUTE"`, `"HOUR"`, or `"DAY"` - `reminder_value`: non-negative integer (e.g. `30` for "30 minutes before") - `clear_reminder` (update_task only): remove reminder - The correct wire format uses **dot-notation** subfields (`reminder.reminderUnit`, `reminder.reminderValue`, `reminder.reminderType`, `reminder.localId`) — flat top-level keys, JSON-string, and bracket-notation are silently ignored by the server. ### Fixed - `update_task` docstring: removed the "reminders not supported" warning — the v1.1.2 write format was flat, which the FiZ encoder silently drops; the dot-notation variant works on both Free and Premium accounts. ### Investigation notes (2026-04-17) - Verified via isolated fuzz test (fresh test task per variant): only dot-notation succeeds; every other encoding is accepted with HTTP 200 and `lastAction: UPDATED` but the reminder remains at default `{reminderType: NONE, reminderValue: 0}`. - `reminder.localId` is optional. - Partial block updates (e.g. only `reminder.reminderType=NONE`) return `task reminder invalid` — the full inactive block must be sent to clear. - Valid `reminderUnit` values: `MINUTE`, `HOUR`, `DAY`. `WEEK` is rejected by the API enum decoder. - Reminder + recurrency can be set in a single `taskupdate2` call without interference. ## [1.1.2] – 2026-04-17 ### Fixed - `update_task`: removed non-functional reminder write parameters (`reminder_unit`, `reminder_value`, `clear_reminder`) — exhaustive FW_DEBUG testing (flat params, JSON-string, PHP-bracket, all string values, with/without `localId`, alternative endpoints) on both Free and Premium accounts confirmed that `taskupdate2` silently ignores all reminder fields; historical SNOOZE reminders were set via the mobile app's Service Worker which transforms requests in ways not reproducible via direct API - `update_task`: docstring now explicitly states reminders are read-only - SPEC.md: documented reminder write limitation with investigation findings - CLAUDE.md: updated reminder row to reflect read-only status ### Investigation notes - Tested formats: flat int params, flat string params, JSON-encoded string value, PHP-bracket notation (`reminder[reminderUnit]=DAY`), no-`localId` variant - Tested endpoints: `tasksetalert`, `taskalertput`, `taskreminderset`, `taskalert`, `tasknotification` — all return `"The call X is not registered"` - Verified on both test account (Free) and real account (Premium) — same result - Recurrency write via flat params is confirmed working (separate from reminder) --- ## [1.1.1] – 2026-04-17 ### Fixed - `update_task`: recurrency and reminder fields now sent as flat top-level parameters instead of nested objects — the FiZ `Ai()` encoder does not support nested objects; `recurrencyDescriptor`/`reminder` keys are never sent, fields go directly to top level (e.g. `recurrency=WEEKLY`, `reminderUnit=DAY` rather than `recurrencyDescriptor={...}`) - SPEC.md and CLAUDE.md corrected to document the flat encoding --- ## [1.1.0] – 2026-04-17 ### Added - `update_task`: recurrency parameters (`recurrency`, `recurrency_interval`, `rrule`, `clear_recurrency`) — set or remove task recurrence rules via `recurrencyDescriptor` - `update_task`: reminder parameters (`reminder_unit`, `reminder_value`, `clear_reminder`) — set or remove task reminders via `reminder` - SPEC.md: documented `recurrencyDescriptor` and `reminder` fields for `taskupdate2` (verified via JS-Bundle xb-Encoder / fc-Encoder) --- ## [1.0.1] – 2026-04-17 ### Added - IMPORTANT confirmation notes in docstrings for write operations (`toggle_task`, `like_post`) - `[project.urls]` section in `pyproject.toml` with Gitea repository link - Language note in CLAUDE.md explaining German/English split - `tests/README.md` documentation for running integration tests ### Changed - `.gitignore` patterns now recursive (test_*.py without leading slash) - CLI help text updated (removed "(read-only)" qualifier) - `clear_list()` now logs exception reasons for failed deletions - `get_categories()` docstring clarifies custom vs. system category locale behavior ### Fixed - Exception handling in `clear_list()` with detailed logging --- ## [1.0.0] – 2026-04-17 ### Added - `tests/` directory with integration tests (moved from root) - `LICENSE` (MIT, Marcus van Elst) - Date validation (ISO `YYYY-MM-DD`) for all meal-plan tools - `_err()` helper — all tools now return `{"error": "..."}` JSON on failure ### Changed - Version is now a single source of truth in `pyproject.toml`; `__init__.py` reads it via `importlib.metadata` - `create_server()` exported via `__all__` in `__init__.py` - `clear_list` reports partial failures: `{"deleted_count": N, "failed_count": M, "failed_ids": [...]}` - All tool functions have explicit `-> str` return-type annotations - Unified error format: every tool returns `{"error": "message"}` JSON ### Removed - ~50 debug/probe artefact files (`probe_*.py`, `debug_*.py`, `*.txt` outputs) --- ## [0.11.x] – Meal Planner write access ### [0.11.8] - Documented `isRecipe` flag behaviour in `get_recipe_box` ### [0.11.7] - `get_recipe_box` — returns only real recipes (`isRecipe=true`) - Parser fix: `ingredients_parsed` built from free-text, not the API list ### [0.11.6] - `clear_list` — bulk-delete all tasks in a list within one session ### [0.11.5] - `add_meal_note` — add note + serving count to a meal plan slot ### [0.11.4] - `delete_meal_plan_entry` — delete `dish/` and `meal/` entries ### [0.11.3] - `add_meal_to_meal_plan` — structured output (fixed `a00.r.r` array shape) ### [0.11.2] - `add_meal_to_meal_plan` — add free-text meal entry ### [0.11.1] - `add_recipe_to_meal_plan` — structured output after response verified ### [0.11.0] - `add_recipe_to_meal_plan` — add recipe from recipe box to meal plan --- ## [0.10.x] – Meal Planner read access ### [0.10.3] - `get_meal_plan` — `is_from_recipe_box` field via `recipeList[].isRecipe` ### [0.10.2] - `get_meal_plan` — merges `mealList[]` (free-text notes + servings) ### [0.10.1] - `get_meal_plan` — structured output after `mplistinterval` response verified ### [0.10.0] - `get_meal_plan` — read-only, raw JSON (Premium feature) --- ## [0.9.x] – Task recurrency + reminders ### [0.9.1] - Fix `reminder` mapping (`reminderUnit`/`reminderValue`; `value=0` is valid) ### [0.9.0] - `get_tasks` returns `recurrency`, `recurrency_interval`, `rrule`, `reminder` --- ## [0.8.x] – Recipe categories + misc fixes ### [0.8.3] - `OTHER` list type documented and supported; `FW_DEBUG=1` logs unknown task fields ### [0.8.2] - `get_lists()` without scope returns all circles ### [0.8.1] - Fix recipe category handling ### [0.8.0] - `get_recipe_categories` — list available recipe categories - `create_recipe` / `update_recipe` accept `category_ids` --- ## [0.7.x] – Circle management ### [0.7.5] - Primary-circle guard in `update_circle` (`isFirstFamily` check) ### [0.7.4] - `update_circle` — rename a circle ### [0.7.3] - `update_list` — rename, change emoji/colour ### [0.7.2] - `delete_circle` ### [0.7.1] - `get_lists` scope fix; `create_list` with `circle_id`; `delete_list` scope ### [0.7.0] - `create_circle`, `add_member_to_circle` --- ## [0.6.x] – Recipe box ### [0.6.1] - `update_recipe` + fix newline handling in `create_recipe` ### [0.6.0] - `get_recipes`, `get_recipe`, `create_recipe`, `delete_recipe` --- ## [0.5.x] – List management ### [0.5.3] - Category auto-assign hint in `create_task` docstring ### [0.5.2] - Quantity convention documented in `create_task` docstring ### [0.5.1] - `emoji` + `color` in `get_lists` / `create_list` ### [0.5.0] - `create_list`, `delete_list` --- ## [0.4.x] – Category management + task fields - `create_category`, `delete_category` - `create_task` / `update_task` support `due_date`, `assignee`, `list_id` --- ## [0.3.x] – Task write access - `create_task`, `update_task`, `toggle_task`, `delete_task` --- ## [0.2.x] – Activity feed - `get_activities`, `like_post` --- ## [0.1.0] – Initial release - `get_circles`, `get_members`, `get_lists`, `get_tasks`, `get_categories` - Session strategy: login → API calls → logout per tool invocation - OS keyring credential storage - MCP server via FastMCP [1.0.0]: https://gitea.gecheckt.de/marcus/mcp-familywall/compare/v0.11.8...v1.0.0