Files
mcp-familywall/CHANGELOG.md
T
marcus 4c1e4e2c23 feat(tasks): support reminder write via dot-notation (v1.2.0)
- Add reminder_unit, reminder_value to create_task
- Add reminder_unit, reminder_value, clear_reminder to update_task
- Wire format verified: reminder.reminderUnit / .reminderValue /
  .reminderType (SNOOZE=active, NONE=clear) / .localId (optional)
- Valid units: MINUTE, HOUR, DAY (WEEK rejected by enum decoder)
- Clear requires full inactive block; partial updates reject with
  "task reminder invalid"
- Flat top-level keys, JSON string and bracket notation are silently
  ignored by the server — confirmed via isolated fuzz per variant
- Update SPEC.md, CLAUDE.md, README.md, CHANGELOG.md
- Remove outdated "not supported" warning in update_task docstring
2026-04-17 22:41:16 +02:00

278 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.2.0] 2026-04-17
### Added
- **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