- api/action_catalog.py: every MCP tool's kind, stage of the work and gate in one place (a test
keeps it and the tools in step); steps now carry their stage.
- api/ai_task_changes.py: changes the user makes in Anomalous while an AI works become steps of
its task, reach the AI once with its next call (kind "change": keep it), and the activity
entry names the task; the activity page links to it ("AI task ->").
- api/ai_task_runs.py: run watching moved out of ai_tasks.py (600-line rule); a step a restart
left "running" is marked stopped when the record is read again.
- Pictures: inspector / compare with canvas / keep as tools on hover instead of three buttons
under every picture; tick any two (any step or task) and compare from the bar at the foot of
the page; the results strip shows thumbnails again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Gallery and Activity pages get "Canvas vs. newest picture": the comparison window on
the newest output PNG and the canvas, so hand edits since the last run show too (the
activity log only knows Anomalous's own canvas writes) and the picture's values can go
back onto the canvas.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ComfyUI takes undo steps on mouse-up and key-up; a drag-and-drop ends in
neither, and writes made in click handlers or after a fetch landed in no
step, so Ctrl+Z could undo the step before instead. canvas_history.js asks
for a step after each write (applied values, drops, created or inserted
nodes, recipes, prompt notes).
A drop's receipt also pops up at the top right with Undo (shared with the
receipt's own button); prompt nodes made by a drop on empty canvas can be
undone there. canvas_undo.js keeps what each canvas activity entry did, in
full, while the page is open; the log offers Undo while nothing changed it
since. Entries that removed nodes or rewired existing ones, seeds, and
choices this computer no longer has are never offered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scan page now says which models are unmatched or not scanned yet (type, folder,
why Civitai had nothing) and what each scan did, model by model; rows open the model,
scan it, look it up again or search Civitai. The progress box shows the counts and,
when floating, a way to the result. The activity log records a scan when it ends with
its result, and model edits (from -> to) and deletions (files moved) in detail.
- scraper.py reports one JSON line per changed model (--report-file); a failing model
no longer ends the scan. Unmatched info keeps why (not_found / network / offline);
online scans look network/offline ones up again. After two models in a row without
an answer the rest of the scan infers from the files (--civitai-down for the next
folders) instead of waiting out every timeout.
- civitai_client.py: the network side moved out of scraper.py; tells a 404 from
Civitai being unreachable (CivitaiUnreachable).
- api/scan_report.py: ScanJob turns a scan's reports into one result, kept as the last
scan (/anomalous/last_scan) and logged; /anomalous/scan_model opens a listed model.
- /anomalous/scan_all takes picked or listed models as `targets`, so one scan has one
result; scan_summary lists unmatched and new models with their reason.
- Activity middleware takes details a handler attaches (request[ACTIVITY_DETAIL]).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new Activity page on the rail (and the home page's recent list) shows, by day,
what the plugin changed. Record only; undo comes later (AD-018).
- api/activity_log.py keeps the newest 500 entries in the ComfyUI user folder.
A middleware records this plugin's and Anomalous_TTS's write requests after
they succeed (including the 200 + {"status": "error"} style as failure), from
one route table; the log never fails the request it records.
- activity_canvas.js: a press inside Anomalous snapshots the canvas; the next
press or key outside it (or the next press inside) logs the difference, so
every button, drag and dialog that writes nodes is covered and the user's own
edits are not. Opening another workflow is logged as that. <html> carries an
Anomalous class and does not count as the plugin's interface.
- activity_diff.js: pure snapshot and difference; activity_log.js: client and
wording; ui_activity.js: the page (filters, details, find on canvas, clear)
and the home list.
- Tests: tests/activity_diff.mjs, tests/test_activity_log.py (local).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>