Absorbs contributor PR #3544 (@rodboev, closes#3340) with two fixes:
1. DETECTION VOCAB (would never fire): the original gated on action names
{save,create,update,upsert}, which don't match the real agent tool enums —
memory.action is add|replace|remove, skill_manage.action is
create|patch|edit|delete|write_file|remove_file. Split into per-tool
predicates with the correct vocabularies: _isMemorySave gates memory on
{add,replace}; _isSkillUpdate gates skill_manage on {create,patch,edit,
write_file}. Deletions excluded so the saved/updated verbs stay accurate;
running/errored excluded.
2. SNAPSHOT/RESTORE PERSISTENCE (Codex catch): classification lived only on the
row._tcData JS property, which does NOT survive the outerHTML/innerHTML
snapshot+restore the live tool-call group uses on session switch/restore —
a restored memory/skill row would be re-counted as a generic tool and the
suffix would silently vanish. buildToolCard now also stamps durable
data-memory-save / data-skill-update attributes, and _syncToolCallGroupSummary
counts them as a fallback when _tcData is absent. Verified live across a real
outerHTML round-trip: label identical before/after.
Replaces the PR's static source assertions with a node-driven behavioral test
(11 cases) covering the real action vocabularies, exclusions, case-insensitivity,
null-arg safety, and the durable-attribute persistence guard.
Co-authored-by: rodboev <rodboev@users.noreply.github.com>