v0.5.0 — Welle 6: tree wipe
Welle 6 — tree wipe. gramps_delete_all_objects empties a tree completely, so a reset to
exactly one source file is now export → wipe → import instead of one delete call per object.
- New destructive tool
gramps_delete_all_objects(confirm, expected_count)behind the existing
GRAMPS_ENABLE_DESTRUCTIVE=1gate. Both arguments are mandatory:expected_countmust equal
the tree's live total, so nothing is deleted unless the caller counted the tree first. A counts
read that comes back empty is refused as well, rather than lettingexpected_count=0through
without the tree's real size ever being established. - Completion is confirmed by polling
object_countsto zero, never/api/tasks/. Requires
OWNER role. The call can run for minutes, so the failure modes are classified rather than
guessed: a read timeout on the POST, or a 502/503/504 from a reverse proxy in front of a
synchronous deployment, falls through to the counts poll instead of being reported as a
failure — a connect timeout, where the request never landed, still fails fast, as does any
other status. If the delete was accepted but the counts cannot then be read, the call raises
DeleteAllStateUnknownErrorand points atgramps_get_object_counts: the counts, not the
response, are the authority on what happened to the tree. - Fix: orphaned-note cleanup after
gramps_delete_person/gramps_delete_blog_postnow skips
transport failures (connection reset, read timeout) as well as HTTP errors. Previously a
network blip while tidying up notes propagated out of a delete that had already succeeded,
so the caller got a bare network error instead of the before/after/deleted result this server
exists to guarantee. A failure that is not a failed request still propagates. Pre-existing
behaviour, not introduced by Welle 6. - Fix:
gramps_import_fileno longer reports a legitimately empty import as a timeout. An
import that adds nothing now returnsadded: 0once the counts have held steady for 30s,
instead of running the full 300s and raisingImportTimeoutErrorfor a success. - Packaging:
mcpis now bounded to>=1.2.0,<2. mcp 2.0.0 removedmcp.server.fastmcp
outright, whichserver.pyimports, so an unbounded requirement makesdocker buildproduce
an image that builds fine and crashes on import. Raise the bound only together with the port
tomcp.server.mcpserver.MCPServer— that is a real port, not a rename. - Docs/build hygiene:
.env.examplenow names all four tools the destructive gate unlocks — it
had omitted the wipe, which is the one with no undo, in the file you read while deciding
whether to enable the gate..dockerignorenow excludes.env*,.venv/and.git/rather
than the bare name.env. - Internals: the three 401→relogin branches were consolidated into one helper (with the
characterization tests they never had), andimport_file's polling loop was extracted as
_wait_for_counts, now shared with the wipe. CI runs the 243-test suite alongside ruff.
Tools: 27 with the destructive gate off, 31 with it on.