π 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 themain@79cb9f5whole-codebase review (3 high, 8 medium, 9 low), covering MCP safety, stdio-stream purity,HttpClientlifecycle, archive-repack structure preservation, and on-disk persistence durability. Phases 1β3 are complete (see below).
Fixed
- MCP
remove_comic_pageRead-Only Bypass:RemoveComicPagenow callsEnsureWriteAccess()before removing a page and defaults todryRun = 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:
AppLoggernow writes console diagnostics tostderrinstead ofstdout, andInkTag.Mcpforces the host logging pipeline to stderr (LogToStandardErrorThreshold). The MCP server previously emitted initialization banners and warning/error log lines ontostdout, interleaving plain text into the JSON-RPC message stream. TheInkTag.Cli--jsonoutput is likewise no longer polluted by Core log lines. - Scraper
HttpClientSocket Exhaustion: IntroducedInkTag.Core.Net.SharedHttpClient, a process-wide pooledHttpClient(SocketsHttpHandler, 2-minutePooledConnectionLifetime).RateLimitedHttpClient,MetadataScraperServicecover-thumbnail downloads, andBulkScrapeQueueServicenow use it instead of allocating a newHttpClientper candidate / per service instance, which under a large bulk scrape could exhaust sockets and ephemeral ports. Per-request time limits are enforced with linkedCancellationTokenSources. - Scraper Cache Lost on One-Shot Runs:
MetadataScraperServiceandComicVineProviderare nowIDisposableand 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 singleinktag scrapecommand or MCP scrape tool call exited before the write fired and never persisted anything. The CLIscrapecommand and thesearch_external_metadata,scrape_comic_metadata, andbulk_scrape_directoryMCP tools now dispose the service. - Stale Untagged Count After Save All:
MainWindowViewModel.SaveAllAsyncnow recomputes the untagged / modified counts and re-applies the active filter once every saved item has flipped toHasEmbeddedXml = true/IsDirty = false, mirroring the refresh the bulk auto-tag apply path already performs. Previously, after auto-tagging a comic and clicking Save All, theUntagged (N)label and filter could remain stale because it relied solely on per-itemPropertyChangednotifications. - README Accuracy Pass: Corrected inaccurate claims in
README.mdβ test count (94 β 211), required SDK (10.0 / 9.0 / 8.0β10.0only, matching thenet10.0target), a non-existentCtrl+Mhotkey, "reading and writing.cbr" (writes always repack to.cbz), the missingremove_comic_page/strip-intro/remove-pagecommands, MCP tool parameter names (filePath/directoryPathβpath/directory), the "atomically" claim onrestore_batch_job(#21), and thecheck_komga_server/audit_komga_librarydescriptions. 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 missingremove_comic_page/check_komga_server/sync_komga_book_or_series/audit_komga_libraryentries added), staleMetadataBackupService/PerceptualHashService/KomgaSyncService/ cover-extraction method signatures, non-existent GUI ViewModel names (ScraperMatchViewModeletc.), theLruImageCache"auto-disposes evicted bitmaps" claim (disposal was removed in v0.13.0),restore_comic_backupparameter (timestampβbackupId), the "atomic" batch-rollback wording, and the missingstrip-intro/remove-pageCLI subcommands. - Auto-Update Always Fell Back to Browser on macOS/Linux:
UpdateService.CheckForUpdatesAsyncnow gates onIsInstalledMode(manager)instead of Velopack's ownmanager.IsInstalled, matching the check already used byDownloadAndApplyUpdateAsync.manager.IsInstalledonly recognizes a Squirrel-style Windows install, so on a properly installed macOS.appbundle 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 VelopackUpdateInfo. That meant the apply step's in-place-update path β despite already being correctly gated onIsInstalledModeβ was unreachable on those platforms, since it requires a non-nullUpdateInfoto 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.TestConnectionAsyncand the internalGetJsonSafeAsync<T>helper (backingGetLibrariesAsync,FindBookByFilePathAsync,FindSeriesByPathOrNameAsync,GetUntaggedOrErrorBooksAsync) now retry up to 2 additional times, 750ms apart, on a transient network exception (HttpRequestException,SocketException, orIOExceptionwrapping aSocketException) before giving up. Previously a single-shot failure like a momentary "No route to host" on the machine hostingInkTag.Mcp(e.g. its network stack not yet warm right after the MCP process starts) was surfaced immediately asconnected: falsefromcheck_komga_server, even though the very next attempt would succeed against the same reachable server. - Scrape Applied Metadata Twice with Divergent Merge Modes:
MetadataScraperService.AutoScrapeComicAsyncno longer mutates the caller'sComicInfo. It returns the raw fetched issue metadata on the newScrapeResult.FetchedMetadata, and the singleApplyMetadatacall at write time owns the merge mode. PreviouslyAutoScrapeComicAsyncpre-applied the fetched data underSettings.DefaultMergeMode, then the CLIscrapecommand / MCPscrape_comic_metadatatool re-applied the already-merged object under the user'smode, somode: "overwrite"was partially ignored and<Notes>attribution could be merged twice. The unusedScrapeResult.TargetComicproperty was removed.
π¦ Downloads & Installation Notes
π macOS Installation Note
Because InkTag is currently unnotarized:
- Drag
InkTag.appinto/Applications. - 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.