Task configuration:
{"task_id": "04", "task_name": "\u5220\u9664\u67d0\u4e2a\u724c\u7ec4,\u7136\u540e\u64a4\u9500\u64cd\u4f5c", "description": "\u6dfb\u52a0\u4e00\u4e2a\"ielts\"\u7684\u724c\u7ec4\uff0c\u5220\u9664\uff0c\u7136\u540e\u64a4\u9500\u5220\u9664", "application_info": {"name": "anki", "executable_path": "/home/agent/anki/out/pyenv/bin/python", "args": ["/home/agent/anki/tools/run.py"], "cwd": "/home/agent/anki"}, "task_parameters": {"deck_name": "ielts"}, "instruction_template": "\u6dfb\u52a0\u4e00\u4e2a\"${deck_name}\"\u7684\u724c\u7ec4\uff0c\u5220\u9664\uff0c\u7136\u540e\u64a4\u9500\u5220\u9664", "evaluation_setup": {"scripts": [{"role": "hook", "path": "hooker.js", "dependency": ["../common/hooker_common.js"]}, {"role": "handler", "path": "handler.py"}], "timeout": 60}, "events": {"deck_added": {"description": "\u6570\u636e\u5e93\u4e2d\u6dfb\u52a0\u6210\u529f", "is_key_step": true, "key_step_index": 1, "key_step_name": "\u6570\u636e\u5e93\u4e2d\u6dfb\u52a0\u6210\u529f"}, "deck_removed": {"description": "\u6570\u636e\u5e93\u4e2d\u5220\u9664\u6210\u529f", "is_key_step": true, "key_step_index": 2, "key_step_name": "\u6570\u636e\u5e93\u4e2d\u5220\u9664\u6210\u529f"}, "undo_removed": {"description": "\u64a4\u9500\u5220\u9664", "is_key_step": true, "key_step_index": 3, "key_step_name": "\u64a4\u9500\u5220\u9664"}}, "success_conditions": ["deck_removed"], "sql_path": "/home/agent/.local/share/Anki2/sam/collection.anki2", "total_key_steps": 2, "mcp_servers": [{"command": "/home/agent/anki-mcp-server/.venv/bin/python", "args": ["/home/agent/anki-mcp-server/run_server.py"]}]}

Hook script:
//! The script only tested in x86-64!

const TRACE_FUNCTION = [
    "storage_add_deck",
    "storage_remove_deck",
    "service_undo"
]
function initHooks() {
    // iterate function name and addr, init it.
    for (const function_name of TRACE_FUNCTION){
        initHook(function_name, TRACE_MAPS[function_name]);
    }
}
initHooks();
sendLog("info", "add hooks done");

Evaluation handler:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
sys.path.append(os.path.dirname(__file__))
from common import *

def handle_storage_add_deck(context: Context,message) -> Status:
    context.update_database()
    deck : Deck = sorted(AnkiObjMap().array_by_type("deck"),key=lambda x: x.mtime,reverse=True)
    status = Status()
    if deck[0].name == tp.deck_name:
        status.emit(EventDeckAdded())   
        status.mark_progress()
    return status

def handle_storage_remove_deck(context: Context,message) -> Status:
    context.update_database()
    status = Status()
    if all([deck.name != tp.deck_name for deck in AnkiObjMap().array_by_type("deck")]):
        status.emit(EventDeckRemoved())   
        status.mark_progress()
    return status


def handle_service_undo(context: Context,message) -> Status:
    time.sleep(1)
    context.update_database()
    status = Status()
    if any([deck.name == tp.deck_name for deck in AnkiObjMap().array_by_type("deck")]):
        status.emit(EventUndoRemoved())
    return status

TRACE_HANDLERS = {
    "storage_remove_deck": handle_storage_remove_deck,
    "storage_add_deck": handle_storage_add_deck,
    "service_undo" : handle_service_undo,
}   
dependency_graph = {
    deck_added_ : [],
    deck_removed_ : [deck_added_],
    undo_removed_ : [deck_removed_]
}
finished_list = [
    undo_removed_
]

bind_handlers(TRACE_HANDLERS,dependency_graph,finished_list)