09bd24a9e1
- Add 38 unit tests covering fw_client, recipes, lists, and server modules - Test error handling: top-level ex/un, nested a00.un.un/a00.ex.ex, successful responses - Test ingredients_parsed parser: newlines, empty lines, commas, headings - Test list name translation: SYS-CAT-SHOPPINGLIST, SYS-CAT-TODOS, unknown names - Test date validation: ISO YYYY-MM-DD format enforcement - Test error response helper: JSON format, Unicode, special characters - All tests use unittest.mock (stdlib), no external mocking libraries - No API calls — all HTTP interactions mocked - Framework: pytest with asyncio support - Run: uv run pytest tests/test_unit.py -v Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
11 KiB
11 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Versioning Policy
This project follows Semantic Versioning (SemVer). Breaking changes (removed tools, changed parameters) increment the major version.
[1.4.0] – 2026-04-17
Added
- Unit test suite (
tests/test_unit.py) — comprehensive tests for core modulesfw_client.py: Error handling (top-levelex/un, nesteda00.un.un/a00.ex.ex, successful responses)recipes.py:ingredients_parsedparser (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_commentresponse parser: corrected response structure froma00.r.rwithmetaIdto nesteda00.r.r.comment.commentId; response now includes"created": trueflagadd_commenterror handling: now returns error messages directly instead of warnings
Added
delete_wall_post— permanently delete a wall post using themetadeleteendpoint (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_postssupersedes the activity-listing functionality ofget_activities(which continues to exist for backward compatibility)like_postalready supports both wall posts and activities; verified to work with metaIds from bothget_wall_postsandget_activities- Post IDs are in the format
wall/<familyid>_<postid>
[1.2.0] – 2026-04-17
Added
- Unlike support for
like_post: passinglike=Falsenow removes a STAR reaction viaadd=$empty, remove.0=STAR(array dot-notation). New optionalmoodparameter (default"STAR"). - Reminder write support for
create_taskandupdate_task:reminder_unit:"MINUTE","HOUR", or"DAY"reminder_value: non-negative integer (e.g.30for "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_taskdocstring: 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: UPDATEDbut the reminder remains at default{reminderType: NONE, reminderValue: 0}. reminder.localIdis optional.- Partial block updates (e.g. only
reminder.reminderType=NONE) returntask reminder invalid— the full inactive block must be sent to clear. - Valid
reminderUnitvalues:MINUTE,HOUR,DAY.WEEKis rejected by the API enum decoder. - Reminder + recurrency can be set in a single
taskupdate2call 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/withoutlocalId, alternative endpoints) on both Free and Premium accounts confirmed thattaskupdate2silently 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 APIupdate_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-localIdvariant - 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 FiZAi()encoder does not support nested objects;recurrencyDescriptor/reminderkeys are never sent, fields go directly to top level (e.g.recurrency=WEEKLY,reminderUnit=DAYrather thanrecurrencyDescriptor={...})- 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 viarecurrencyDescriptorupdate_task: reminder parameters (reminder_unit,reminder_value,clear_reminder) — set or remove task reminders viareminder- SPEC.md: documented
recurrencyDescriptorandreminderfields fortaskupdate2(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 inpyproject.tomlwith Gitea repository link- Language note in CLAUDE.md explaining German/English split
tests/README.mddocumentation for running integration tests
Changed
.gitignorepatterns now recursive (test_*.py without leading slash)- CLI help text updated (removed "(read-only)" qualifier)
clear_list()now logs exception reasons for failed deletionsget_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__.pyreads it viaimportlib.metadata create_server()exported via__all__in__init__.pyclear_listreports partial failures:{"deleted_count": N, "failed_count": M, "failed_ids": [...]}- All tool functions have explicit
-> strreturn-type annotations - Unified error format: every tool returns
{"error": "message"}JSON
Removed
- ~50 debug/probe artefact files (
probe_*.py,debug_*.py,*.txtoutputs)
[0.11.x] – Meal Planner write access
[0.11.8]
- Documented
isRecipeflag behaviour inget_recipe_box
[0.11.7]
get_recipe_box— returns only real recipes (isRecipe=true)- Parser fix:
ingredients_parsedbuilt 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— deletedish/andmeal/entries
[0.11.3]
add_meal_to_meal_plan— structured output (fixeda00.r.rarray 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_boxfield viarecipeList[].isRecipe
[0.10.2]
get_meal_plan— mergesmealList[](free-text notes + servings)
[0.10.1]
get_meal_plan— structured output aftermplistintervalresponse verified
[0.10.0]
get_meal_plan— read-only, raw JSON (Premium feature)
[0.9.x] – Task recurrency + reminders
[0.9.1]
- Fix
remindermapping (reminderUnit/reminderValue;value=0is valid)
[0.9.0]
get_tasksreturnsrecurrency,recurrency_interval,rrule,reminder
[0.8.x] – Recipe categories + misc fixes
[0.8.3]
OTHERlist type documented and supported;FW_DEBUG=1logs 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 categoriescreate_recipe/update_recipeacceptcategory_ids
[0.7.x] – Circle management
[0.7.5]
- Primary-circle guard in
update_circle(isFirstFamilycheck)
[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_listsscope fix;create_listwithcircle_id;delete_listscope
[0.7.0]
create_circle,add_member_to_circle
[0.6.x] – Recipe box
[0.6.1]
update_recipe+ fix newline handling increate_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_taskdocstring
[0.5.2]
- Quantity convention documented in
create_taskdocstring
[0.5.1]
emoji+coloringet_lists/create_list
[0.5.0]
create_list,delete_list
[0.4.x] – Category management + task fields
create_category,delete_categorycreate_task/update_tasksupportdue_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