{"id":346388,"date":"2026-08-21T14:05:48","date_gmt":"2026-08-21T14:05:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/unused-image-cleaner\/"},"modified":"2026-10-07T17:21:16","modified_gmt":"2026-10-07T17:21:16","slug":"janitorix-media-audit","status":"publish","type":"plugin","link":"https:\/\/frp.wordpress.org\/plugins\/janitorix-media-audit\/","author":17924966,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.0","stable_tag":"1.1.0","tested":"7.1.3","requires":"6.2","requires_php":"7.4","requires_plugins":null,"header_name":"Janitorix Media Audit","header_author":"Monowar Hossain","header_description":"Finds unused images and removes them safely \u2014 by proving they are unused first.","assets_banners_color":"0e453c","last_updated":"2026-10-07 17:21:16","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/devmonowar.github.io\/janitorix-media-audit\/","header_author_uri":"https:\/\/devmonowar.github.io\/","rating":5,"author_block_rating":0,"active_installs":0,"downloads":483,"num_ratings":2,"support_threads":1,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"kstmonowar","date":"2026-08-21 14:05:34","revision":3659154},"1.0.1":{"tag":"1.0.1","author":"kstmonowar","date":"2026-08-22 17:32:45","revision":3660965},"1.0.2":{"tag":"1.0.2","author":"kstmonowar","date":"2026-08-30 03:30:53","revision":3672000},"1.0.3":{"tag":"1.0.3","author":"kstmonowar","date":"2026-09-21 16:04:17","revision":3705907},"1.0.4":{"tag":"1.0.4","author":"kstmonowar","date":"2026-09-21 16:16:33","revision":3705931},"1.0.5":{"tag":"1.0.5","author":"kstmonowar","date":"2026-09-23 09:17:48","revision":3708954},"1.1.0":{"tag":"1.1.0","author":"kstmonowar","date":"2026-10-07 17:21:16","revision":3733065}},"upgrade_notice":{"1.1.0":"<p>New Alt Text screen with rule-based and optional AI suggestions. Nothing changes about existing scans or settings; AI stays off unless you enable it with your own key.<\/p>","1.0.5":"<p>Review notice added; uninstall and performance fixes. No settings change needed.<\/p>","1.0.4":"<p>New SEO image detection may change some verdicts. Rescan after updating.<\/p>","1.0.3":"<p>Closes a case where an image still in use could be judged unused. Rescan after updating.<\/p>","1.0.2":"<p>Scanner accuracy, safety gate, and Plugin Check fixes. Rescan after updating.<\/p>","1.0.1":"<p>Corrects the author link on the Plugins screen. No functional changes.<\/p>","1.0.0":"<p>First stable release. Several Risk Engine and ACF detection fixes change what a small number of images are priced or recognised as \u2014 rescan after updating to pick them up.<\/p>","0.6.0":"<p>This release can move images to Trash. Everything before it only reported.<\/p>"},"ratings":{"1":0,"2":0,"3":0,"4":0,"5":2},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3660965,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3660965,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3660965,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3660965,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.1.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3660965,"resolution":"1","location":"assets","locale":"","width":2560,"height":1860},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3660965,"resolution":"2","location":"assets","locale":"","width":2560,"height":1882},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3660965,"resolution":"3","location":"assets","locale":"","width":2560,"height":2800},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3660965,"resolution":"4","location":"assets","locale":"","width":2560,"height":1986},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3660965,"resolution":"5","location":"assets","locale":"","width":2560,"height":1948},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3660965,"resolution":"6","location":"assets","locale":"","width":2560,"height":1960},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3733008,"resolution":"7","location":"assets","locale":"","width":2560,"height":2800},"screenshot-8.png":{"filename":"screenshot-8.png","revision":3733008,"resolution":"8","location":"assets","locale":"","width":2560,"height":2800}},"screenshots":{"1":"The dashboard \u2014 a verdict first, with the reasons behind it","2":"Every unused image with its confidence, its risk, and what to do about it. A row that cannot be trashed has no checkbox","3":"Why an image scored what it did \u2014 where the plugin looked, what it found, and how the risk was reached","4":"An image that is in use, with every reference that proves it, and the rule that refuses to trash it","5":"The behaviour you cannot switch off, stated rather than offered","6":"Every scan kept as a snapshot a later one never rewrites","7":"The alt text audit \u2014 every image missing or weakening its alt text, with a suggestion ready","8":"Optional AI suggestions with one-click provider presets and test connection (off by default)"}},"plugin_section":[],"plugin_tags":[17214,3786,84,233,146945],"plugin_category":[50],"plugin_contributors":[269133],"plugin_business_model":[],"class_list":["post-346388","plugin","type-plugin","status-publish","hentry","plugin_tags-alt-text","plugin_tags-cleanup","plugin_tags-media","plugin_tags-media-library","plugin_tags-unused-images","plugin_category-media","plugin_contributors-kstmonowar","plugin_committers-kstmonowar"],"banners":{"banner":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/banner-772x250.png?rev=3660965","banner_2x":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/banner-1544x500.png?rev=3660965","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/icon-128x128.png?rev=3660965","icon_2x":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/icon-256x256.png?rev=3660965","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-1.png?rev=3660965","caption":"The dashboard \u2014 a verdict first, with the reasons behind it"},{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-2.png?rev=3660965","caption":"Every unused image with its confidence, its risk, and what to do about it. A row that cannot be trashed has no checkbox"},{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-3.png?rev=3660965","caption":"Why an image scored what it did \u2014 where the plugin looked, what it found, and how the risk was reached"},{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-4.png?rev=3660965","caption":"An image that is in use, with every reference that proves it, and the rule that refuses to trash it"},{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-5.png?rev=3660965","caption":"The behaviour you cannot switch off, stated rather than offered"},{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-6.png?rev=3660965","caption":"Every scan kept as a snapshot a later one never rewrites"},{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-7.png?rev=3733008","caption":"The alt text audit \u2014 every image missing or weakening its alt text, with a suggestion ready"},{"src":"https:\/\/ps.w.org\/janitorix-media-audit\/assets\/screenshot-8.png?rev=3733008","caption":"Optional AI suggestions with one-click provider presets and test connection (off by default)"}],"raw_content":"<!--section=description-->\n<p>Most cleanup plugins tell you an image is unused. This one tells you <strong>how sure it is, and why<\/strong>.<\/p>\n\n<p>That difference matters, because the cost of being wrong is not symmetric. Leaving an unused image costs you a few kilobytes. Deleting a used one breaks your site \u2014 and you may not find out for weeks.<\/p>\n\n<p>Version 1.1.0 adds an alt text audit with rule-based and optional AI suggestions \u2014 see below.<\/p>\n\n<p><strong><a href=\"https:\/\/devmonowar.github.io\/blog\/how-to-find-unused-images-in-wordpress\/\">Read the full guide<\/a><\/strong> \u2014 why \"unattached\" is not the same as \"unused\", the places a reference hides, and how to check by hand \u00b7 <strong><a href=\"https:\/\/devmonowar.github.io\/janitorix-media-audit\/\">Plugin page<\/a><\/strong> \u00b7 <strong><a href=\"https:\/\/github.com\/devmonowar\/janitorix-media-audit\">Development on GitHub<\/a><\/strong> \u2014 report issues or contribute.<\/p>\n\n<h4>What it actually does<\/h4>\n\n<p>Scanners search every place an image can hide: featured images and post attachments, post content, Gutenberg blocks and synced patterns, full-site-editing templates, the Customizer, theme options, widgets, menus, Elementor, ACF, WooCommerce, and your theme's PHP, CSS, and JavaScript files.<\/p>\n\n<p>Then two independent judgements are made about every image:<\/p>\n\n<ul>\n<li><strong>Confidence<\/strong> \u2014 how sure we are the image is unused<\/li>\n<li><strong>Risk<\/strong> \u2014 how much damage deleting it would cause if we are wrong<\/li>\n<\/ul>\n\n<p>These are never blended into one score. A site logo nobody references and a stray upload nobody references look identical to a confidence score, and demand opposite actions.<\/p>\n\n<h4>Alt text audit<\/h4>\n\n<p>A separate screen lists every image missing alt text (or carrying a weak one like \"IMG_2034\"), suggests a replacement built from the filename, title, or parent post, and applies it only when you say so \u2014 with undo. The suggestion is editable: apply it as-is or write your own words. Images can be marked decorative, a Dashboard card tracks your coverage, and <code>wp janitorix alt stats<\/code> reports coverage for scripting. Nothing here affects confidence, risk, or any deletion recommendation.<\/p>\n\n<h4>Optional AI suggestions<\/h4>\n\n<p>The alt text screen can also ask an AI model \u2014 but only if you enable it under Settings and add your own API key. One-click presets for Gemini, OpenAI, Groq, and OpenRouter fill in the endpoint and a working default model, so setup is \"pick yours, paste the key\" \u2014 and a test-connection button confirms it works before you spend anything. The plugin ships no key and makes no AI calls on its own. Each suggestion is reviewed in the textbox before anything is saved, exactly like a rule-based one, with rate-limit handling and cached answers so you never pay twice for the same image.<\/p>\n\n<h4>External services<\/h4>\n\n<p>AI suggestions are off by default. When you enable them and save a key, each image you ask about is sent \u2014 resized to at most 1024px \u2014 together with its filename and its parent post's title, to the service at the base URL you configured. The plugin itself stores nothing externally; what the service does with that data is governed by its own terms, which you accept when you create your key. Providers differ \u2014 some train on API data, some do not \u2014 so read your chosen service before enabling. Examples (your own service's terms apply, not these examples):<\/p>\n\n<ul>\n<li>OpenAI \u2014 <a href=\"https:\/\/openai.com\/policies\/terms-of-use\">Terms<\/a> \u00b7 <a href=\"https:\/\/openai.com\/policies\/privacy-policy\">Privacy<\/a><\/li>\n<li>Anthropic \u2014 <a href=\"https:\/\/www.anthropic.com\/legal\">Legal<\/a> \u00b7 <a href=\"https:\/\/www.anthropic.com\/legal\/privacy\">Privacy<\/a><\/li>\n<li>Google Gemini \u2014 <a href=\"https:\/\/ai.google.dev\/gemini-api\/terms\">Terms<\/a> \u00b7 <a href=\"https:\/\/policies.google.com\/privacy\">Privacy<\/a><\/li>\n<li>Groq \u2014 <a href=\"https:\/\/groq.com\/terms-of-use\">Terms<\/a> \u00b7 <a href=\"https:\/\/groq.com\/privacy-policy\">Privacy<\/a><\/li>\n<li>OpenRouter \u2014 <a href=\"https:\/\/openrouter.ai\/terms\">Terms<\/a> \u00b7 <a href=\"https:\/\/openrouter.ai\/privacy\">Privacy<\/a><\/li>\n<\/ul>\n\n<p>No other part of this plugin contacts any external service. Scans, suggestions, and reports all run on your own site.<\/p>\n\n<h4>What it refuses to do<\/h4>\n\n<ul>\n<li>It will not recommend deleting anything if it could not search enough of your site. Below 70% coverage, it says so and recommends a rescan instead.<\/li>\n<li>It will not offer Trash for anything at Medium risk or above, no matter how confident it is.<\/li>\n<li>It will never delete your site logo, icon, or header \u2014 those are refused outright, not merely scored low.<\/li>\n<li>It will not touch an image uploaded in the last 24 hours, because you probably have plans for it.\n\n<ul>\n<li>It never deletes anything in one step. Trash first, always, and only from the Trash can anything be permanently removed.<\/li>\n<li>It never contacts any external service on its own. The only network call the plugin can ever make is an AI suggestion you explicitly ask for, after enabling it with your own key.<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<h4>Every number shows its work<\/h4>\n\n<p>Open any image and you can see which scanner found what, how strong each piece of evidence was, and exactly why the plugin reached its conclusion. A confidence score you cannot inspect is a number you have no reason to trust.<\/p>\n\n<h4>Honest about its limits<\/h4>\n\n<p>A perfect scan reports 97%, not 100%. Proving an image is <em>used<\/em> takes one piece of evidence; proving it is <em>unused<\/em> means proving the absence of evidence everywhere \u2014 and \"everywhere\" is not somewhere you can finish visiting. Theme frameworks store images in ways nobody can fully predict, and page builders can assemble URLs at render time.<\/p>\n\n<p>The plugin reports the honest number rather than a comfortable one.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin through Plugins &gt; Add New, or upload the ZIP via Plugins &gt; Add New &gt; Upload.<\/li>\n<li>Activate it through the Plugins menu.<\/li>\n<li>Open the new <strong>Janitorix<\/strong> menu in your WordPress admin sidebar.<\/li>\n<li>Click <strong>Start the first scan<\/strong> on the Dashboard. Nothing is deleted until you decide to act on a recommendation, and nothing is ever removed permanently without first going through the Trash.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"can%20it%20delete%20an%20image%20my%20site%20is%20using%3F\"><h3>Can it delete an image my site is using?<\/h3><\/dt>\n<dd><p>That is the failure mode the entire design exists to prevent, and it is why coverage floors, risk ceilings, and never-delete rules all sit between a scan and any action. But no scanner can see a URL assembled at runtime, or an image embedded in a newsletter you sent last year. Trash first, and check before emptying it.<\/p><\/dd>\n<dt id=\"does%20it%20support%20my%20page%20builder%3F\"><h3>Does it support my page builder?<\/h3><\/dt>\n<dd><p>Elementor is supported directly. For builders that are not \u2014 Divi, Bricks, Oxygen \u2014 a fallback scanner sweeps for image references it does not understand. It will not raise your confidence score, because it cannot prove it searched thoroughly. It can and does prevent deletions.<\/p><\/dd>\n<dt id=\"why%20is%20my%20confidence%20score%20low%3F\"><h3>Why is my confidence score low?<\/h3><\/dt>\n<dd><p>Open the dashboard. If a scanner failed, it is named. If coverage is below 70%, it says so. The score is never lowered without a reason you can read.<\/p><\/dd>\n<dt id=\"is%20anything%20deleted%20automatically%3F\"><h3>Is anything deleted automatically?<\/h3><\/dt>\n<dd><p>No. Nothing is ever deleted without you clicking, and nothing is deleted in one step.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20i%20uninstall%20it%3F\"><h3>What happens when I uninstall it?<\/h3><\/dt>\n<dd><p>Every table and option the plugin created is removed. Your media is not touched.<\/p><\/dd>\n<dt id=\"how%20do%20i%20find%20unused%20images%20in%20wordpress%3F\"><h3>How do I find unused images in WordPress?<\/h3><\/dt>\n<dd><p>The Media Library's \"Unattached\" filter is not the answer \u2014 see below. Check post content, post meta (ACF fields, page builders, featured images), options (logo, Customizer, widgets), and theme files, by filename and by attachment ID. Or run a scan here: every image gets a confidence score with the evidence behind it.<\/p><\/dd>\n<dt id=\"is%20it%20safe%20to%20delete%20unused%20media%20in%20wordpress%3F\"><h3>Is it safe to delete unused media in WordPress?<\/h3><\/dt>\n<dd><p>Only after two conditions: the image is proven unused (not merely unattached), and deletion goes through Trash first so a mistake is reversible. This plugin enforces both \u2014 it refuses Trash for anything at Medium risk or above, and nothing is ever deleted in one step.<\/p><\/dd>\n<dt id=\"why%20does%20my%20media%20library%20keep%20growing%3F\"><h3>Why does my media library keep growing?<\/h3><\/dt>\n<dd><p>Every upload stays unless someone removes it, and WordPress generates several resized copies per upload. Unused originals plus their thumbnails accumulate silently. A periodic scan keeps it flat.<\/p><\/dd>\n<dt id=\"does%20deleting%20images%20hurt%20seo%3F\"><h3>Does deleting images hurt SEO?<\/h3><\/dt>\n<dd><p>It can, in ways no database scan sees. An image can be unused on your site and still rank in Google Images or be hotlinked elsewhere \u2014 check Search Console, Performance, Images before a bulk delete. Deleted URLs return 404, which loses any signal they had; redirect if they mattered. Sitemaps list images too, and take time to regenerate. When in doubt, Trash and wait before emptying.<\/p><\/dd>\n<dt id=\"what%20is%20the%20difference%20between%20%22unattached%22%20and%20%22unused%22%3F\"><h3>What is the difference between \"unattached\" and \"unused\"?<\/h3><\/dt>\n<dd><p>\"Unattached\" only means the image was not uploaded inside a post. It says nothing about whether anything references it \u2014 a logo, a Customizer image and most page-builder images are all \"unattached\" and all in use. Unused means no reference anywhere, which takes a real search to establish.<\/p><\/dd>\n<dt id=\"does%20the%20ai%20feature%20send%20my%20images%20anywhere%3F\"><h3>Does the AI feature send my images anywhere?<\/h3><\/dt>\n<dd><p>Only when you ask it to, image by image. Enabling AI and saving your own key sends nothing by itself. Each \"Suggest with AI\" click sends that one image (resized to at most 1024px), its filename and its parent post's title to the service you configured \u2014 see \"External services\" above for exactly what goes where. Rule-based suggestions never leave your site.<\/p><\/dd>\n<dt id=\"does%20alt%20text%20change%20on%20its%20own%3F\"><h3>Does alt text change on its own?<\/h3><\/dt>\n<dd><p>No. Nothing is applied until you click Save or Apply on that image, and every change keeps an undo. Marking decorative, editing the suggestion by hand, or dismissing an AI suggestion all work the same way \u2014 your call, reversible.<\/p><\/dd>\n<dt id=\"is%20the%20alt%20text%20shown%20here%20the%20same%20as%20on%20the%20page%3F\"><h3>Is the alt text shown here the same as on the page?<\/h3><\/dt>\n<dd><p>Not always. This screen reads the alt text stored on the image itself; a theme or page builder may override it where the image is shown, so what a visitor actually hears can differ. Fix the stored text here first \u2014 that is the source everything else falls back to.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>New: alt text audit \u2014 a dedicated screen listing images with missing or weak alt text, with rule-based suggestions (filename, title, parent post), one-click apply with undo, decorative marking, and a Dashboard coverage card.<\/li>\n<li>New: editable suggestion box \u2014 apply the suggestion as-is or write your own words; hand-written text is capped and kept for undo like any apply.<\/li>\n<li>New: optional AI suggestions (BYOK) \u2014 per-image \"Suggest with AI\" with one-click presets (Gemini, OpenAI, Groq, OpenRouter), test connection, rate-limit handling, and cached answers. Reviewed before saving, off by default; rule-based suggestions never need it.<\/li>\n<li>New: <code>wp janitorix alt stats<\/code> \u2014 read-only coverage report for the command line, with <code>--format=json<\/code> for scripting.<\/li>\n<li>New: \"Remove key\" checkbox in Settings \u2014 delete the stored API key without disabling anything else.<\/li>\n<li>Fixed: replacing an image under the same attachment ID no longer serves the previous file's cached AI suggestion.<\/li>\n<li>Hardening: AI requests no longer follow HTTP redirects, so the API key stays with the configured endpoint.<\/li>\n<li>Improved: when the AI service declines, Test connection and the Alt Text screen now quote the service's own reason (HTTP code + message) instead of only \"answered unexpectedly\".<\/li>\n<li>Note: the alt text audit never touches confidence, risk, or deletion recommendations.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Added: review notice (15-day) + footer rating link.<\/li>\n<li>Fixed: uninstall now removes the review state too.<\/li>\n<li>Performance: scanners build lazily (no cost on frontend views); version constant hardcoded.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>New: SEO and social image keys (Yoast, Rank Math, SEOPress) are now read as declared image fields, so an og:image stored as a bare attachment ID keeps its image referenced.<\/li>\n<li>Fixed: CSV formula injection in exports.<\/li>\n<li>Fixed: <code>SHOW TABLES LIKE<\/code> escaping, delete-permanent rescan, and coverage floor handling.<\/li>\n<li>Changed: Plugin URI, Author URI, short description and Packagist metadata now point at the author's site.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Fixed: an image used only in a widget, the Customizer or a theme option could be judged unused.<\/li>\n<li>Fixed: trashing or restoring an image asked for a rescan that was not needed.<\/li>\n<li>Fixed: a scanned image was reported as never scanned once the site had changed.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Fixed: scanner accuracy bugs in Gutenberg, Widget, Generic Fallback, and ACF scanners.<\/li>\n<li>Fixed: SafetyEngine now reads verdicts from the current scan only.<\/li>\n<li>Fixed: AttachmentResolver no longer resolves external URLs by basename fallback.<\/li>\n<li>Fixed: GenericFallbackScanner now reports database errors instead of swallowing them silently.<\/li>\n<li>Fixed: outside_uploads no longer flags bare filenames without path separators.<\/li>\n<li>Fixed: ScanFingerprint no longer recomputes per row on the Images screen.<\/li>\n<li>Fixed: ImageValueExtractor no longer reports non-image attachments as missing.<\/li>\n<li>Fixed: Plugin Check security and database query warnings.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fixed: the author link on the Plugins screen went to a WordPress.org profile page instead of the author's own site.<\/li>\n<li>Added: a link to the full guide in the plugin description.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First stable release<\/li>\n<li>The Dashboard's Confidence card read 0% on every scan \u2014 the figure was calculated and displayed but never stored<\/li>\n<li>An image held back because it was uploaded recently now says how much longer it stays protected, instead of only that it is<\/li>\n<li>The Images list shows each image's upload date, which is also what the date filters above it match on<\/li>\n<li>Uninstall now removes the cached file hashes it wrote onto attachments, not only its tables, options and your saved decisions<\/li>\n<li>Risk Engine: a WooCommerce product's gallery images are now priced at their correct impact instead of the lower, generic rate a field-name collision was giving them<\/li>\n<li>Risk Engine: the site logo, icon, header, and background are held at the highest risk level whenever the Customizer Scanner cannot confirm them \u2014 previously this floor was documented but not enforced<\/li>\n<li>Risk Engine: a store's own placeholder image is now recognised and priced instead of going unnoticed<\/li>\n<li>Fixed a false \"in use\" reading on WooCommerce-imported images, caused by treating the import's own source-URL metadata as a usage reference<\/li>\n<li>ACF: a Relationship field configured to browse only the Media Library is now trusted as image evidence, the same as an Image or Gallery field<\/li>\n<li>Scan History lists only finished scans, and now shows the storage each one actually recovered<\/li>\n<li>Delete Permanently's confirmation is now enforced by the server, not only by the browser dialog<\/li>\n<li>A reminder to keep a recent backup, shown before a permanent delete<\/li>\n<li>The Images screen now labels a row it declines to offer for Trash as Protected, instead of leaving it blank<\/li>\n<\/ul>\n\n<h4>0.6.0<\/h4>\n\n<ul>\n<li>The write path: Trash, Restore, and Permanent Delete, each gated by the Safety Engine<\/li>\n<li>A restore record is written before anything is touched, so recovery does not depend on WordPress having a media trash<\/li>\n<li>Bulk trash \u2014 every image still checked individually<\/li>\n<\/ul>\n\n<h4>0.5.0<\/h4>\n\n<ul>\n<li>Calibration suite: seeded fixtures with known answers, run against the real pipeline<\/li>\n<li>A report of what would be deleted, having deleted nothing<\/li>\n<\/ul>\n\n<h4>0.4.0<\/h4>\n\n<ul>\n<li>Dashboard, Images, Image Details, Scan History, Settings<\/li>\n<\/ul>\n\n<h4>0.3.0<\/h4>\n\n<ul>\n<li>Risk Engine, Recommendation Engine, and the explanation layer<\/li>\n<\/ul>\n\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>Persistence, resumable batched scans, and fingerprint-based caching<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Scanner layer and Confidence Engine<\/li>\n<\/ul>","raw_excerpt":"Finds unused images and proves it \u2014 confidence, risk, safe delete. Plus an alt text audit with optional AI suggestions.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/346388","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=346388"}],"author":[{"embeddable":true,"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/kstmonowar"}],"wp:attachment":[{"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=346388"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=346388"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=346388"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=346388"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=346388"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/frp.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=346388"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}