Skip to content

v0.13.1

Latest

Choose a tag to compare

@github-actions github-actions released this 15 Sep 10:34

πŸš€ What's Changed in v0.13.1

Added

  • Review Remediation Plan: Added docs/review-remediation-plan-2026-09-01.md β€” a phased, branch-mapped implementation plan for the findings of the main @ 79cb9f5 whole-codebase review (3 high, 8 medium, 9 low), covering MCP safety, stdio-stream purity, HttpClient lifecycle, archive-repack structure preservation, and on-disk persistence durability. Phases 1–3 are complete (see below).

Fixed

  • MCP remove_comic_page Read-Only Bypass: RemoveComicPage now calls EnsureWriteAccess() before removing a page and defaults to dryRun = true, matching every other mutating MCP tool. Previously it committed by default and could delete pages / repack archives even when the server was started in strict read-only mode (INKTAG_MCP_READ_ONLY=true / --read-only).
  • MCP stdio Protocol Stream Corruption: AppLogger now writes console diagnostics to stderr instead of stdout, and InkTag.Mcp forces the host logging pipeline to stderr (LogToStandardErrorThreshold). The MCP server previously emitted initialization banners and warning/error log lines onto stdout, interleaving plain text into the JSON-RPC message stream. The InkTag.Cli --json output is likewise no longer polluted by Core log lines.
  • Scraper HttpClient Socket Exhaustion: Introduced InkTag.Core.Net.SharedHttpClient, a process-wide pooled HttpClient (SocketsHttpHandler, 2-minute PooledConnectionLifetime). RateLimitedHttpClient, MetadataScraperService cover-thumbnail downloads, and BulkScrapeQueueService now use it instead of allocating a new HttpClient per candidate / per service instance, which under a large bulk scrape could exhaust sockets and ephemeral ports. Per-request time limits are enforced with linked CancellationTokenSources.
  • Scraper Cache Lost on One-Shot Runs: MetadataScraperService and ComicVineProvider are now IDisposable and flush the ComicVine response cache synchronously on dispose. Previously the 7-day disk cache was only written by a 2-second debounce timer, so a single inktag scrape command or MCP scrape tool call exited before the write fired and never persisted anything. The CLI scrape command and the search_external_metadata, scrape_comic_metadata, and bulk_scrape_directory MCP tools now dispose the service.
  • Stale Untagged Count After Save All: MainWindowViewModel.SaveAllAsync now recomputes the untagged / modified counts and re-applies the active filter once every saved item has flipped to HasEmbeddedXml = true / IsDirty = false, mirroring the refresh the bulk auto-tag apply path already performs. Previously, after auto-tagging a comic and clicking Save All, the Untagged (N) label and filter could remain stale because it relied solely on per-item PropertyChanged notifications.
  • README Accuracy Pass: Corrected inaccurate claims in README.md β€” test count (94 β†’ 211), required SDK (10.0 / 9.0 / 8.0 β†’ 10.0 only, matching the net10.0 target), a non-existent Ctrl+M hotkey, "reading and writing .cbr" (writes always repack to .cbz), the missing remove_comic_page / strip-intro / remove-page commands, MCP tool parameter names (filePath/directoryPath β†’ path/directory), the "atomically" claim on restore_batch_job (#21), and the check_komga_server / audit_komga_library descriptions. Also dropped "Komga" from the Upcoming roadmap (already shipped in v0.11.1).
  • Wiki Accuracy Pass (docs/wiki/, .agents/skills/comic-metadata-curator/SKILL.md): Reconciled the Layer 2 wiki with the current code β€” test count (184 β†’ 211), MCP tool count (14 β†’ 18, with the missing remove_comic_page / check_komga_server / sync_komga_book_or_series / audit_komga_library entries added), stale MetadataBackupService / PerceptualHashService / KomgaSyncService / cover-extraction method signatures, non-existent GUI ViewModel names (ScraperMatchViewModel etc.), the LruImageCache "auto-disposes evicted bitmaps" claim (disposal was removed in v0.13.0), restore_comic_backup parameter (timestamp β†’ backupId), the "atomic" batch-rollback wording, and the missing strip-intro / remove-page CLI subcommands.
  • Auto-Update Always Fell Back to Browser on macOS/Linux: UpdateService.CheckForUpdatesAsync now gates on IsInstalledMode(manager) instead of Velopack's own manager.IsInstalled, matching the check already used by DownloadAndApplyUpdateAsync. manager.IsInstalled only recognizes a Squirrel-style Windows install, so on a properly installed macOS .app bundle or Linux AppImage the check step always took the "portable" branch and queried the GitHub Releases API directly, which only returns a release page URL and never a Velopack UpdateInfo. That meant the apply step's in-place-update path β€” despite already being correctly gated on IsInstalledMode β€” was unreachable on those platforms, since it requires a non-null UpdateInfo to run, so the user was always sent to the browser to download a new build manually.
  • Komga Connection False Negatives on Transient Network Blips: KomgaClient.TestConnectionAsync and the internal GetJsonSafeAsync<T> helper (backing GetLibrariesAsync, FindBookByFilePathAsync, FindSeriesByPathOrNameAsync, GetUntaggedOrErrorBooksAsync) now retry up to 2 additional times, 750ms apart, on a transient network exception (HttpRequestException, SocketException, or IOException wrapping a SocketException) before giving up. Previously a single-shot failure like a momentary "No route to host" on the machine hosting InkTag.Mcp (e.g. its network stack not yet warm right after the MCP process starts) was surfaced immediately as connected: false from check_komga_server, even though the very next attempt would succeed against the same reachable server.
  • Scrape Applied Metadata Twice with Divergent Merge Modes: MetadataScraperService.AutoScrapeComicAsync no longer mutates the caller's ComicInfo. It returns the raw fetched issue metadata on the new ScrapeResult.FetchedMetadata, and the single ApplyMetadata call at write time owns the merge mode. Previously AutoScrapeComicAsync pre-applied the fetched data under Settings.DefaultMergeMode, then the CLI scrape command / MCP scrape_comic_metadata tool re-applied the already-merged object under the user's mode, so mode: "overwrite" was partially ignored and <Notes> attribution could be merged twice. The unused ScrapeResult.TargetComic property was removed.


πŸ“¦ Downloads & Installation Notes

🍏 macOS Installation Note

Because InkTag is currently unnotarized:

  1. Drag InkTag.app into /Applications.
  2. Run the following command in Terminal to clear the download quarantine:
    xattr -cr /Applications/InkTag.app

(Alternatively, go to System Settings > Privacy & Security and click Open Anyway).

πŸ€– Model Context Protocol (MCP) Server Usage

  • macOS (bundled): /Applications/InkTag.app/Contents/MacOS/InkTag.Mcp
  • Windows / Linux / macOS (standalone downloads): Use the dedicated InkTag-Mcp-* packages.