<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RawCull</title><link>https://techrawcull.netlify.app/</link><description>Recent content on RawCull</description><generator>Hugo</generator><language>en</language><atom:link href="https://techrawcull.netlify.app/index.xml" rel="self" type="application/rss+xml"/><item><title>How PhotoAIKit Is Constructed</title><link>https://techrawcull.netlify.app/docs/packages/photoaikit/</link><pubDate>Thu, 30 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/packages/photoaikit/</guid><description>&lt;h1 id="how-photoaikit-is-constructed"&gt;How PhotoAIKit Is Constructed&lt;a class="td-heading-self-link" href="#how-photoaikit-is-constructed" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;PhotoAIKit is a reusable Swift package extracted from application code. Its most
important achievement is not merely that CLIP and SAM 3 run. It is that reusable
AI behavior has been separated from RawCull&amp;rsquo;s UI, RAW-file handling, paths,
sandbox rules, and culling policy.&lt;/p&gt;
&lt;p&gt;This document explains the construction from the bottom up and gives the reason
for each boundary.&lt;/p&gt;
&lt;h2 id="1-begin-with-the-package-boundary"&gt;1. Begin With The Package Boundary&lt;a class="td-heading-self-link" href="#1-begin-with-the-package-boundary" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The package owns:&lt;/p&gt;</description></item><item><title>Thumbnails and Scan Pipeline</title><link>https://techrawcull.netlify.app/docs/thumbnail/</link><pubDate>Wed, 15 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/thumbnail/</guid><description>&lt;h1 id="thumbnails-and-scan-pipeline"&gt;Thumbnails and Scan Pipeline&lt;a class="td-heading-self-link" href="#thumbnails-and-scan-pipeline" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull separates catalog scanning, thumbnail preloading, UI-driven thumbnail requests, and full-size preview extraction. They share RawParserKit and disk-cache infrastructure, but they have deliberately different memory-admission rules.&lt;/p&gt;
&lt;p&gt;The key current invariant is: &lt;strong&gt;catalog preloading warms the 200 px grid cache and disk cache, but only UI demand may admit an image to the preview-size RAM cache&lt;/strong&gt;. This keeps scan order from displacing the images the user is actively viewing.&lt;/p&gt;</description></item><item><title>How PhotoAnalysisKit Is Constructed</title><link>https://techrawcull.netlify.app/docs/packages/photoanalysiskit/</link><pubDate>Thu, 30 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/packages/photoanalysiskit/</guid><description>&lt;h1 id="how-photoanalysiskit-is-constructed"&gt;How PhotoAnalysisKit Is Constructed&lt;a class="td-heading-self-link" href="#how-photoanalysiskit-is-constructed" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;PhotoAnalysisKit is the reusable measurement layer extracted from RawCull. It
turns a decoded &lt;code&gt;CGImage&lt;/code&gt; plus neutral capture metadata into sharpness,
saliency, focus evidence, and an optional focus-mask image. It can also create
opaque Apple Vision feature prints.&lt;/p&gt;
&lt;p&gt;The package measures a photo; it does not decide whether to keep it. That
distinction prevents image-processing code from becoming coupled to RawCull&amp;rsquo;s
files, settings, views, caches, or culling policy.&lt;/p&gt;</description></item><item><title>How RawCull Loads and Uses CLIP</title><link>https://techrawcull.netlify.app/docs/ai/clip-in-rawcull/</link><pubDate>Wed, 29 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/ai/clip-in-rawcull/</guid><description>&lt;h1 id="how-rawcull-loads-and-uses-clip"&gt;How RawCull Loads and Uses CLIP&lt;a class="td-heading-self-link" href="#how-rawcull-loads-and-uses-clip" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull supports two CLIP models:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpenAI CLIP ViT-B/32&lt;/strong&gt;, which processes a 224 × 224 image;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenCLIP DataComp ViT-B-32-256&lt;/strong&gt;, which processes a 256 × 256 image.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The user selects one model in &lt;strong&gt;Settings &amp;gt; AI&lt;/strong&gt;. That one selection defines the
vector space used for both image-to-image similarity and text-to-image semantic
search. RawCull never mixes vectors from the two models.&lt;/p&gt;
&lt;p&gt;This page starts with the basic idea behind CLIP and then follows the current
source code from application startup, through model validation and Core AI
inference, to search results, burst groups, and persisted artifacts.&lt;/p&gt;</description></item><item><title>Memory Cache</title><link>https://techrawcull.netlify.app/docs/cache/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/cache/</guid><description>&lt;h1 id="cache-system"&gt;Cache System&lt;a class="td-heading-self-link" href="#cache-system" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull uses several caches because RAW decoding is expensive and because different UI surfaces need different image sizes. The normal thumbnail path is layered RAM -&amp;gt; disk -&amp;gt; RAW extraction. The zoom path has its own disk cache for larger embedded JPEGs. Burst analysis has a separate JSON cache for derived analysis data.&lt;/p&gt;
&lt;h2 id="source-map"&gt;Source Map&lt;a class="td-heading-self-link" href="#source-map" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Cache&lt;/th&gt;
					&lt;th&gt;Main files&lt;/th&gt;
					&lt;th&gt;Stores&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Preview memory cache&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Actors/SharedMemoryCache.swift&lt;/code&gt;, &lt;code&gt;Model/Cache/CachedThumbnail.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Larger &lt;code&gt;NSImage&lt;/code&gt; thumbnails for detail/loupe use&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Grid memory cache&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Actors/SharedMemoryCache.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Small grid thumbnails, downscaled before insertion&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Thumbnail disk cache&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Actors/DiskCacheManager.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;JPEG thumbnail files under the app cache directory&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Full-size JPEG disk cache&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Actors/FullSizeJPGDiskCache.swift&lt;/code&gt;, &lt;code&gt;Model/Handlers/ZoomPreviewHandler.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Larger embedded JPEG previews for zoom&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Burst analysis cache&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Actors/BurstAnalysisCache.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;JSON snapshots of embeddings, scores, groups, rankings, and review state&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Diagnostics&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Model/Cache/CacheDelegate.swift&lt;/code&gt;, &lt;code&gt;Model/Cache/CacheStatistics.swift&lt;/code&gt;, &lt;code&gt;Views/Diagnostics/MemoryDiagnosticsView.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Hit/miss/eviction/pressure counters&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="thumbnail-lookup"&gt;Thumbnail Lookup&lt;a class="td-heading-self-link" href="#thumbnail-lookup" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A[&amp;#34;Request thumbnail&amp;#34;] --&amp;gt; B{&amp;#34;Preview memory cache?&amp;#34;}
 B --&amp;gt;|&amp;#34;hit&amp;#34;| C[&amp;#34;Return NSImage&amp;#34;]
 B --&amp;gt;|&amp;#34;miss&amp;#34;| D{&amp;#34;Disk thumbnail cache?&amp;#34;}
 D --&amp;gt;|&amp;#34;hit&amp;#34;| E[&amp;#34;Decode JPEG and refill memory&amp;#34;]
 D --&amp;gt;|&amp;#34;miss&amp;#34;| F[&amp;#34;RawParserKit extractThumbnail&amp;#34;]
 F --&amp;gt; G[&amp;#34;Create NSImage&amp;#34;]
 G --&amp;gt; H[&amp;#34;Store preview memory&amp;#34;]
 G --&amp;gt; I[&amp;#34;Store grid memory copy&amp;#34;]
 G --&amp;gt; J[&amp;#34;Save disk JPEG&amp;#34;]&lt;/pre&gt;
&lt;p&gt;The same lookup idea is used by preload and on-demand requests. &lt;code&gt;ScanAndCreateThumbnails&lt;/code&gt; warms the cache after a catalog opens. &lt;code&gt;ThumbnailLoader&lt;/code&gt; and &lt;code&gt;RequestThumbnail&lt;/code&gt; resolve individual thumbnails while the user scrolls.&lt;/p&gt;</description></item><item><title>AI Model Download Service</title><link>https://techrawcull.netlify.app/docs/ai/aimodeldownloads/</link><pubDate>Mon, 10 Aug 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/ai/aimodeldownloads/</guid><description>&lt;h1 id="ai-model-download-service"&gt;AI model download service&lt;a class="td-heading-self-link" href="#ai-model-download-service" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull supports exactly three optional model bundles:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Model&lt;/th&gt;
					&lt;th&gt;PhotoAIKit bundle&lt;/th&gt;
					&lt;th&gt;Runtime asset&lt;/th&gt;
					&lt;th&gt;Use&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;DataComp CLIP&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIP-DataComp&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ViT-B-32-256-datacomp_s34b_b86k_float16_static.aimodel&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Similarity and semantic search&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OpenAI CLIP&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIP-OpenAI&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;clip-vit-base-patch32_float16_static.aimodel&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Similarity and semantic search&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Meta SAM 3&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SAM3&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sam3_float16.aimodel&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Promptable segmentation&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;SigLIP2 and EfficientSAM are not part of the RawCull download catalogue or
release manifest. Do not include their bundles, notices, archives, or asset-pack
IDs in a RawCull model release.&lt;/p&gt;</description></item><item><title>AI Model Licence</title><link>https://techrawcull.netlify.app/docs/ai/licenceprocedure/</link><pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/ai/licenceprocedure/</guid><description>&lt;h1 id="ai-model-licence-and-provenance-clearance-procedure"&gt;AI model licence and provenance clearance procedure&lt;a class="td-heading-self-link" href="#ai-model-licence-and-provenance-clearance-procedure" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Status: publication hold&lt;br&gt;
Last reviewed: 2026-08-03&lt;/p&gt;
&lt;h2 id="purpose-and-current-decision"&gt;Purpose and current decision&lt;a class="td-heading-self-link" href="#purpose-and-current-decision" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This document defines how RawCull clears the DataComp CLIP, OpenAI CLIP, and
Meta SAM 3 model packs for public download. It covers technical provenance,
licence evidence, upstream contacts, questions to ask, acceptable answers, and
the final release gate.&lt;/p&gt;
&lt;p&gt;No &lt;code&gt;.aar&lt;/code&gt; model archive has been uploaded. Do not create a public GitHub
Release, publish a download manifest, or change a production descriptor to
&lt;code&gt;ready&lt;/code&gt; until every model is either:&lt;/p&gt;</description></item><item><title>How RawCullCore Is Constructed</title><link>https://techrawcull.netlify.app/docs/packages/rawcullcore/</link><pubDate>Thu, 30 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/packages/rawcullcore/</guid><description>&lt;h1 id="how-rawcullcore-is-constructed"&gt;How RawCullCore Is Constructed&lt;a class="td-heading-self-link" href="#how-rawcullcore-is-constructed" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCullCore is the small domain layer at the center of RawCull. It does not
decode or analyze photos. Instead, it receives file metadata and measurements
already produced elsewhere, groups sequential files into bursts, and ranks the
candidates using deterministic culling rules.&lt;/p&gt;
&lt;p&gt;Its main architectural value is that a recommendation can be tested without
opening a RAW file, running Vision, creating a Metal context, loading
application settings, or constructing a view model.&lt;/p&gt;</description></item><item><title>Memory Pressure</title><link>https://techrawcull.netlify.app/docs/memorypressure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/memorypressure/</guid><description>&lt;h1 id="memory-pressure"&gt;Memory Pressure&lt;a class="td-heading-self-link" href="#memory-pressure" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull can hold many images in memory while scanning and culling. The memory-pressure code exists to keep the app responsive when macOS reports pressure and to make cache behavior visible during development.&lt;/p&gt;
&lt;h2 id="source-map"&gt;Source Map&lt;a class="td-heading-self-link" href="#source-map" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;File&lt;/th&gt;
					&lt;th&gt;Role&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Actors/SharedMemoryCache.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Owns cache limits, memory-pressure dispatch source, pressure counters, and cache clearing&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Model/ViewModels/MemoryViewModel.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Samples total system memory, used system memory, app memory, and pressure threshold for the UI&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Model/Cache/CacheConfig.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Contains &lt;code&gt;CacheRecommendationPolicy&lt;/code&gt; and cache-limit calculation&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Model/ViewModels/MemoryDiagnosticsViewModel.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Writes diagnostics samples for cache/memory review&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Views/Settings/MemoryTab.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Displays memory stats, cache limits, and pressure status&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Views/RawCullSidebarMainView/MemoryWarningLabelView.swift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Shows the sidebar warning during pressure&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="runtime-flow"&gt;Runtime Flow&lt;a class="td-heading-self-link" href="#runtime-flow" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A[&amp;#34;SharedMemoryCache.ensureReady&amp;#34;] --&amp;gt; B[&amp;#34;startMemoryPressureMonitoring&amp;#34;]
 B --&amp;gt; C[&amp;#34;DispatchSourceMemoryPressure&amp;#34;]
 C --&amp;gt; D{&amp;#34;event&amp;#34;}
 D --&amp;gt;|&amp;#34;normal&amp;#34;| E[&amp;#34;refreshConfig from settings/adaptive policy&amp;#34;]
 D --&amp;gt;|&amp;#34;warning&amp;#34;| F[&amp;#34;shrink cache limits to 60 percent&amp;#34;]
 D --&amp;gt;|&amp;#34;critical&amp;#34;| G[&amp;#34;clear memory caches and set 50 MB floor&amp;#34;]
 F --&amp;gt; H[&amp;#34;Notify file handler warning&amp;#34;]
 G --&amp;gt; H
 E --&amp;gt; I[&amp;#34;Clear warning&amp;#34;]&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;SharedMemoryCache&lt;/code&gt; starts monitoring lazily during &lt;code&gt;ensureReady()&lt;/code&gt;. That is called before thumbnail cache use, so the memory-pressure handler is active before large thumbnail work begins.&lt;/p&gt;</description></item><item><title>Evaluating CLIP Models</title><link>https://techrawcull.netlify.app/docs/ai/evaluateclipmodels/</link><pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/ai/evaluateclipmodels/</guid><description>&lt;h1 id="evaluating-clip-models-against-source-framework-cosine-values-and-rawcullfb"&gt;Evaluating CLIP Models Against Source-Framework Cosine Values and RawCullFB&lt;a class="td-heading-self-link" href="#evaluating-clip-models-against-source-framework-cosine-values-and-rawcullfb" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This document is the complete repeatable procedure for validating CLIP model bundles used by RawCullFB. It covers both supported candidates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenAI CLIP ViT-B/32 at 224 × 224.&lt;/li&gt;
&lt;li&gt;OpenCLIP DataComp ViT-B/32-256 with &lt;code&gt;datacomp_s34b_b86k&lt;/code&gt; weights.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SigLIP2 is outside the current evaluation scope.&lt;/p&gt;
&lt;p&gt;The procedure has two independent validation layers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Numerical parity:&lt;/strong&gt; compare embeddings produced by the Core AI bundle with reference embeddings produced by the original Hugging Face Transformers or OpenCLIP implementation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Product behavior:&lt;/strong&gt; use RawCullFB to build a real catalog index, execute the same 77 semantic queries, inspect image-similarity neighborhoods, and measure labeled retrieval quality.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A model must pass both layers. Numerical parity proves that the conversion and integration reproduce the source model; it does not prove that the model retrieves useful photographs. Conversely, plausible search results do not prove that the converted model is correct.&lt;/p&gt;</description></item><item><title>New RawCull AI models</title><link>https://techrawcull.netlify.app/docs/ai/newmodels/</link><pubDate>Mon, 10 Aug 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/ai/newmodels/</guid><description>&lt;h1 id="publishing-new-rawcull-ai-models"&gt;Publishing new RawCull AI models&lt;a class="td-heading-self-link" href="#publishing-new-rawcull-ai-models" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This runbook publishes exactly three optional models:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Model&lt;/th&gt;
					&lt;th&gt;Asset-pack ID&lt;/th&gt;
					&lt;th&gt;Installed destination&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;DataComp CLIP&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;no.blogspot.RawCull.models.clip-datacomp&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Models/CLIP-DataComp&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OpenAI CLIP&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;no.blogspot.RawCull.models.clip-openai&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Models/CLIP-OpenAI&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Meta SAM 3&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;no.blogspot.RawCull.models.sam3&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Models/SAM3&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;SigLIP2 and EfficientSAM are deliberately excluded. Do not add them to the
release staging tree, packaging manifests, download manifest, production
catalogue, settings UI, notices, or tests.&lt;/p&gt;
&lt;p&gt;The examples use the &lt;code&gt;v2&lt;/code&gt; release in
&lt;a href="https://github.com/rsyncOSX/RawCull-AI-Models/releases"&gt;&lt;code&gt;RawCull-AI-Models&lt;/code&gt;&lt;/a&gt;.
Tag names and GitHub release URLs are case-sensitive. If another tag is chosen,
replace &lt;code&gt;v2&lt;/code&gt; everywhere and keep both RawCull manifest URLs identical.&lt;/p&gt;</description></item><item><title>CLIP Model Evaluation Results</title><link>https://techrawcull.netlify.app/docs/ai/evaluation/</link><pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/ai/evaluation/</guid><description>&lt;h1 id="clip-model-evaluation-results"&gt;CLIP Model Evaluation Results&lt;a class="td-heading-self-link" href="#clip-model-evaluation-results" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Report date:&lt;/strong&gt; 2026-08-12&lt;/p&gt;
&lt;p&gt;This report compares the product-behavior results produced by RawCullFB for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenAI CLIP ViT-B/32 at 224 × 224; and&lt;/li&gt;
&lt;li&gt;OpenCLIP DataComp ViT-B/32-256 using the &lt;code&gt;datacomp_s34b_b86k&lt;/code&gt;
checkpoint.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The runs follow the product-behavior portion of
&lt;a href="../evaluateclipmodels/"&gt;Evaluating CLIP Models&lt;/a&gt;. They cover the canonical 77
semantic queries and a complete all-pairs image-similarity pass over 453 indexed
images.&lt;/p&gt;
&lt;p&gt;The reports show that both integrations completed cleanly, neither model shows
semantic collapse, and both produce coherent image-neighbourhood structures.
DataComp is modestly faster and more consistent across paraphrases. Those are
promising sanity-check results, but they are not labeled accuracy metrics.&lt;/p&gt;</description></item><item><title>Concurrency</title><link>https://techrawcull.netlify.app/docs/concurrency-revised/</link><pubDate>Sat, 01 Aug 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/concurrency-revised/</guid><description>&lt;h1 id="concurrency"&gt;Concurrency&lt;a class="td-heading-self-link" href="#concurrency" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This page documents concurrency in the &lt;code&gt;RawCullAIModels&lt;/code&gt; branch of RawCull and in the first-party Swift packages checked out beside it. The audit covers production source in the RawCull app, &lt;code&gt;DecodeEncodeGeneric&lt;/code&gt;, &lt;code&gt;ParseRsyncOutput&lt;/code&gt;, &lt;code&gt;PhotoAIKit&lt;/code&gt;, &lt;code&gt;PhotoAnalysisKit&lt;/code&gt;, &lt;code&gt;RawCullCore&lt;/code&gt;, &lt;code&gt;RawParserKit&lt;/code&gt;, &lt;code&gt;RsyncArguments&lt;/code&gt;, &lt;code&gt;RsyncProcessStreaming&lt;/code&gt;, and &lt;code&gt;RsyncAnalyse&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;RawCull uses concurrency to keep SwiftUI responsive while it scans folders, reads RAW metadata, extracts and caches previews, calculates sharpness, creates similarity artifacts, groups bursts, runs AI models, downloads model assets, and streams rsync output.&lt;/p&gt;</description></item><item><title>How RawParserKit Is Constructed</title><link>https://techrawcull.netlify.app/docs/packages/rawparserkit/</link><pubDate>Thu, 30 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/packages/rawparserkit/</guid><description>&lt;h1 id="how-rawparserkit-is-constructed"&gt;How RawParserKit Is Constructed&lt;a class="td-heading-self-link" href="#how-rawparserkit-is-constructed" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawParserKit is RawCull&amp;rsquo;s camera-file boundary. It knows how Sony ARW and Nikon
NEF files are structured, how to locate their embedded JPEGs and AF metadata,
and how to turn those sources into orientation-normalized images and
display-ready metadata.&lt;/p&gt;
&lt;p&gt;The package stops at decoding. It does not score sharpness, generate embeddings,
group bursts, cache application results, or decide which photo should be kept.&lt;/p&gt;
&lt;h2 id="1-begin-with-the-package-boundary"&gt;1. Begin With The Package Boundary&lt;a class="td-heading-self-link" href="#1-begin-with-the-package-boundary" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;RawParserKit owns:&lt;/p&gt;</description></item><item><title>Focus Mask and Sharpness</title><link>https://techrawcull.netlify.app/docs/focusmask/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/focusmask/</guid><description>&lt;h1 id="focus-mask-and-sharpness"&gt;Focus Mask and Sharpness&lt;a class="td-heading-self-link" href="#focus-mask-and-sharpness" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull&amp;rsquo;s focus system does two related jobs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;produce a visible focus mask for image inspection,&lt;/li&gt;
&lt;li&gt;compute a scalar sharpness score for sorting, burst ranking, and saved scoring.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both jobs use the same core engine, but the UI overlay and the numeric score are not identical. The overlay tries to show useful focus evidence. The score tries to rank files fairly across a catalog or burst.&lt;/p&gt;</description></item><item><title>Detailed Sharpness Scoring</title><link>https://techrawcull.netlify.app/docs/detailsharpnessscoring/</link><pubDate>Wed, 15 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/detailsharpnessscoring/</guid><description>&lt;h1 id="detailed-sharpness-scoring"&gt;Detailed Sharpness Scoring&lt;a class="td-heading-self-link" href="#detailed-sharpness-scoring" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This page explains, step by step, where RawCull computes sharpness scores, what code is involved, what the score means, and which factors can move the result up or down.&lt;/p&gt;
&lt;p&gt;The short version: RawCull does not ask &amp;ldquo;is the whole image contrasty?&amp;rdquo;. It asks &amp;ldquo;how much reliable edge detail exists in the useful part of the image, especially around the subject or the camera AF point?&amp;rdquo;. The score is then used for sharpness sorting, burst ranking, saved scoring results, and inspection badges.&lt;/p&gt;</description></item><item><title>Detailed Focus Mask Computation</title><link>https://techrawcull.netlify.app/docs/detailsfocusmask/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/detailsfocusmask/</guid><description>&lt;h1 id="detailed-focus-mask-computation"&gt;Detailed Focus Mask Computation&lt;a class="td-heading-self-link" href="#detailed-focus-mask-computation" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This page explains, step by step, how RawCull computes the visible focus mask: where the work starts in the UI, which model and engine methods run, how the bitmap overlay is produced, what the intermediate values mean, and which factors can change the final result.&lt;/p&gt;
&lt;p&gt;The short version: the focus mask is not a camera focus-point display. It is a computed overlay built from local edge energy. RawCull first finds useful regions to inspect, then computes a Laplacian edge-energy image, ranks local patches, thresholds the strongest evidence, colorizes it, clips it to the selected patch areas, and finally draws the result over the photo.&lt;/p&gt;</description></item><item><title>Burst Groups</title><link>https://techrawcull.netlify.app/docs/burstgroup/</link><pubDate>Wed, 15 Jul 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/burstgroup/</guid><description>&lt;h1 id="burst-groups"&gt;Burst Groups&lt;a class="td-heading-self-link" href="#burst-groups" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Burst analysis turns a flat catalog into groups of adjacent, visually similar frames. It ranks each multi-frame group, presents review queues, and supports culling decisions such as keeping the best frame, keeping the top two, deferring a group, or setting a manual pick.&lt;/p&gt;
&lt;p&gt;The implementation separates orchestration, Vision feature-print indexing, pure grouping and ranking engines, cache persistence, and the review UI.&lt;/p&gt;
&lt;h2 id="source-map"&gt;Source Map&lt;a class="td-heading-self-link" href="#source-map" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Area&lt;/th&gt;
					&lt;th&gt;Main files&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Analysis orchestration and user actions&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sourcecode/RawCull/RawCull/Model/ViewModels/RawCullViewModel+BurstGrouping.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Similarity indexing and grouping state&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sourcecode/RawCull/RawCull/Model/ViewModels/SimilarityScoringModel.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Pure grouping and ranking&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sourcecode/RawCullCore/Sources/RawCullCore/BurstGroupingEngine.swift&lt;/code&gt;, &lt;code&gt;BurstRankingEngine.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Shared models&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sourcecode/RawCullCore/Sources/RawCullCore/BurstAnalysisModels.swift&lt;/code&gt;, app &lt;code&gt;BurstAnalysisModels.swift&lt;/code&gt;, &lt;code&gt;BurstReviewQueueModels.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cache&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sourcecode/RawCull/RawCull/Actors/BurstAnalysisCache.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Ratings and manual overrides&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CullingModel.swift&lt;/code&gt;, &lt;code&gt;SavedFiles.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Burst home and review list&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BurstGroupsHomeView.swift&lt;/code&gt;, &lt;code&gt;SimilarityGridSelectionView.swift&lt;/code&gt;, &lt;code&gt;CullingGridView.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Single-burst workspace and comparison&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BurstCullingWorkspaceView.swift&lt;/code&gt;, &lt;code&gt;ComparisonGridView.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Tests&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawCullCore/Tests/RawCullCoreTests/BurstGroupingEngineTests.swift&lt;/code&gt;, &lt;code&gt;BurstRankingEngineTests.swift&lt;/code&gt;, app burst/culling tests&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="end-to-end-flow"&gt;End-to-End Flow&lt;a class="td-heading-self-link" href="#end-to-end-flow" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A[&amp;#34;Analyze Bursts&amp;#34;] --&amp;gt; B[&amp;#34;RawCullViewModel.analyzeBursts&amp;#34;]
 B --&amp;gt; C{&amp;#34;Valid BurstAnalysisCache?&amp;#34;}
 C --&amp;gt;|&amp;#34;yes&amp;#34;| D[&amp;#34;Remap cached IDs and apply snapshot&amp;#34;]
 C --&amp;gt;|&amp;#34;no&amp;#34;| E{&amp;#34;Sharpness scores missing?&amp;#34;}
 E --&amp;gt;|&amp;#34;yes&amp;#34;| F[&amp;#34;Calibrate and score target files&amp;#34;]
 E --&amp;gt;|&amp;#34;no&amp;#34;| G[&amp;#34;Reuse scores&amp;#34;]
 F --&amp;gt; H{&amp;#34;Similarity embeddings missing?&amp;#34;}
 G --&amp;gt; H
 H --&amp;gt;|&amp;#34;yes&amp;#34;| I[&amp;#34;Index Vision feature prints&amp;#34;]
 H --&amp;gt;|&amp;#34;no&amp;#34;| J[&amp;#34;Reuse embeddings&amp;#34;]
 I --&amp;gt; K[&amp;#34;Group adjacent frames&amp;#34;]
 J --&amp;gt; K
 K --&amp;gt; L[&amp;#34;Rank multi-frame groups&amp;#34;]
 L --&amp;gt; M[&amp;#34;Apply manual winner overrides&amp;#34;]
 M --&amp;gt; N[&amp;#34;Save cache and review-state snapshots&amp;#34;]
 N --&amp;gt; O[&amp;#34;Show home dashboard and review queues&amp;#34;]&lt;/pre&gt;
&lt;p&gt;Every awaited phase is protected by the analysis generation and selected catalog. A cancelled or superseded run cannot publish late results into a newer catalog.&lt;/p&gt;</description></item><item><title>File Read and Write Reference</title><link>https://techrawcull.netlify.app/docs/filereadandwrite/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/filereadandwrite/</guid><description>&lt;h1 id="file-read-and-write-reference"&gt;File Read and Write Reference&lt;a class="td-heading-self-link" href="#file-read-and-write-reference" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This page lists the main places RawCull reads and writes files. Use it before changing sandbox access, cache locations, persistence, or export behavior.&lt;/p&gt;
&lt;h2 id="file-map"&gt;File Map&lt;a class="td-heading-self-link" href="#file-map" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;File/folder&lt;/th&gt;
					&lt;th&gt;Access&lt;/th&gt;
					&lt;th&gt;Owner&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;User-selected catalog folder&lt;/td&gt;
					&lt;td&gt;Read&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawCullViewModel&lt;/code&gt;, &lt;code&gt;ScanFiles&lt;/code&gt;, &lt;code&gt;DiscoverFiles&lt;/code&gt;, parser package&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;RAW files (&lt;code&gt;.arw&lt;/code&gt;, &lt;code&gt;.nef&lt;/code&gt;)&lt;/td&gt;
					&lt;td&gt;Read&lt;/td&gt;
					&lt;td&gt;scan, thumbnails, focus parsing, zoom, export, diagnostics&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;focuspoints.json&lt;/code&gt; beside catalog&lt;/td&gt;
					&lt;td&gt;Read optional&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ScanFiles&lt;/code&gt; fallback&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;App Support &lt;code&gt;savedfiles.json&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Read/write&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CullingModel&lt;/code&gt;, &lt;code&gt;ReadSavedFilesJSON&lt;/code&gt;, &lt;code&gt;WriteSavedFilesJSON&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;App Support burst cache&lt;/td&gt;
					&lt;td&gt;Read/write/delete&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BurstAnalysisCache&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Thumbnail cache directory&lt;/td&gt;
					&lt;td&gt;Read/write/delete&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DiskCacheManager&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Full-size JPEG preview cache&lt;/td&gt;
					&lt;td&gt;Read/write/prune&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;FullSizeJPGDiskCache&lt;/code&gt;, &lt;code&gt;ZoomPreviewHandler&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Extracted &lt;code&gt;.jpg&lt;/code&gt; sidecars&lt;/td&gt;
					&lt;td&gt;Write&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ExtractAndSaveJPGs&lt;/code&gt;, &lt;code&gt;SaveJPGImage&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;rsync include files / process output&lt;/td&gt;
					&lt;td&gt;Write/read process stream&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ExecuteCopyFiles&lt;/code&gt;, &lt;code&gt;ArgumentsSynchronize&lt;/code&gt;, &lt;code&gt;PrepareOutputFromRsync&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Security-scoped bookmarks&lt;/td&gt;
					&lt;td&gt;Read/write UserDefaults&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;OpencatalogView&lt;/code&gt;, copy workflow&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Settings&lt;/td&gt;
					&lt;td&gt;Read/write UserDefaults&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SettingsViewModel&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="catalog-reads"&gt;Catalog Reads&lt;a class="td-heading-self-link" href="#catalog-reads" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The active catalog comes from the sidebar folder selection. &lt;code&gt;RawCullViewModel.startCatalogLoad(for:)&lt;/code&gt; starts security-scoped access and then runs the scan.&lt;/p&gt;</description></item><item><title>Synchronous Code</title><link>https://techrawcull.netlify.app/docs/heavy/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/heavy/</guid><description>&lt;h1 id="synchronous-code"&gt;Synchronous Code&lt;a class="td-heading-self-link" href="#synchronous-code" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Most RawCull code uses async/await, actors, and task groups. Some Apple framework work is still fundamentally synchronous: ImageIO thumbnail decode, CoreImage RAW rendering, JPEG encoding, and direct binary MakerNote parsing. This page explains where that work lives and how the app keeps it from freezing the UI or starving Swift&amp;rsquo;s cooperative executor.&lt;/p&gt;
&lt;h2 id="source-map"&gt;Source Map&lt;a class="td-heading-self-link" href="#source-map" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Area&lt;/th&gt;
					&lt;th&gt;Files&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Cancellation-aware blocking bridge&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawParserKit/Sources/RawParserKit/CancellableImageIOWork.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Thumbnail extraction&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SonyThumbnailExtractor.swift&lt;/code&gt;, &lt;code&gt;NikonThumbnailExtractor.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Embedded JPEG extraction&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;JPGSonyARWExtractor.swift&lt;/code&gt;, &lt;code&gt;JPGNikonNEFExtractor.swift&lt;/code&gt;, &lt;code&gt;SonyRAWJPEGCreator.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;MakerNote parsing&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SonyMakerNoteParser.swift&lt;/code&gt;, &lt;code&gt;NikonMakerNoteParser.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;App callers&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RequestThumbnail.swift&lt;/code&gt;, &lt;code&gt;ScanAndCreateThumbnails.swift&lt;/code&gt;, &lt;code&gt;ExtractAndSaveJPGs.swift&lt;/code&gt;, &lt;code&gt;ScanAndExtractJPGs.swift&lt;/code&gt;, &lt;code&gt;ZoomPreviewHandler.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Sharpness scoring&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;FocusMaskEngine+Scoring.swift&lt;/code&gt;, &lt;code&gt;FocusMaskEngine+MaskGeneration.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="why-blocking-work-matters"&gt;Why Blocking Work Matters&lt;a class="td-heading-self-link" href="#why-blocking-work-matters" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Swift&amp;rsquo;s cooperative thread pool expects async tasks to suspend instead of occupying threads for long periods. ImageIO and CoreImage calls often do not suspend; they block until decode/render work is done.&lt;/p&gt;</description></item><item><title>Repository Git Workflow</title><link>https://techrawcull.netlify.app/docs/pushpull/</link><pubDate>Sun, 19 Apr 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/pushpull/</guid><description>&lt;h1 id="repository-git-workflow-linear-history"&gt;Repository Git Workflow: Linear History&lt;a class="td-heading-self-link" href="#repository-git-workflow-linear-history" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This page documents the preferred repository workflow for RawCull documentation changes: branch-based development, signed commits when configured, rebasing onto &lt;code&gt;main&lt;/code&gt;, and fast-forward integration without merge commits.&lt;/p&gt;
&lt;h2 id="create-a-branch"&gt;Create a Branch&lt;a class="td-heading-self-link" href="#create-a-branch" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout -b &amp;lt;new-branch&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push --set-upstream origin &amp;lt;new-branch&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="daily-workflow"&gt;Daily Workflow&lt;a class="td-heading-self-link" href="#daily-workflow" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You always work on a dedicated branch. Commit often as you make progress.&lt;/p&gt;
&lt;h3 id="stage-changes"&gt;Stage changes&lt;a class="td-heading-self-link" href="#stage-changes" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="commit"&gt;Commit&lt;a class="td-heading-self-link" href="#commit" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you use the Claude CLI, it can generate a &lt;a href="https://www.conventionalcommits.org/"&gt;Conventional Commits&lt;/a&gt; message from the staged diff:&lt;/p&gt;</description></item><item><title>Sony/Nikon MakerNote Parser</title><link>https://techrawcull.netlify.app/docs/sonymakernoteparser/</link><pubDate>Wed, 25 Mar 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/sonymakernoteparser/</guid><description>&lt;h1 id="sonynikon-makernote-parser"&gt;Sony/Nikon MakerNote Parser&lt;a class="td-heading-self-link" href="#sonynikon-makernote-parser" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull reads autofocus points and embedded JPEG locations directly from RAW metadata. This is implemented in &lt;code&gt;RawParserKit&lt;/code&gt;, while the app consumes the parser through the vendor-neutral &lt;code&gt;RawFormat&lt;/code&gt; protocol.&lt;/p&gt;
&lt;h2 id="source-map"&gt;Source Map&lt;a class="td-heading-self-link" href="#source-map" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Area&lt;/th&gt;
					&lt;th&gt;Files&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Format protocol/registry&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawParserKit/Sources/RawParserKit/RawFormat.swift&lt;/code&gt;, &lt;code&gt;RawFormatRegistry.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Sony parser&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SonyMakerNoteParser.swift&lt;/code&gt;, &lt;code&gt;SonyRawFormat.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Nikon parser&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NikonMakerNoteParser.swift&lt;/code&gt;, &lt;code&gt;NikonRawFormat.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Thumbnail/JPEG extractors&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SonyThumbnailExtractor.swift&lt;/code&gt;, &lt;code&gt;NikonThumbnailExtractor.swift&lt;/code&gt;, &lt;code&gt;JPGSonyARWExtractor.swift&lt;/code&gt;, &lt;code&gt;JPGNikonNEFExtractor.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Diagnostics&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawParserDiagnostics.swift&lt;/code&gt;, app &lt;code&gt;RawFileDiagnostics.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;App scan consumer&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Actors/ScanFiles.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Focus-point normalization&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawCullCore/Sources/RawCullCore/FocusPointParser.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Tests&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawParserKit/Tests/RawParserKitTests/&lt;/code&gt;, &lt;code&gt;RawCullCore/Tests/RawCullCoreTests/FocusPointParserTests.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="vendor-neutral-contract"&gt;Vendor-Neutral Contract&lt;a class="td-heading-self-link" href="#vendor-neutral-contract" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;App code usually does not call &lt;code&gt;SonyMakerNoteParser&lt;/code&gt; or &lt;code&gt;NikonMakerNoteParser&lt;/code&gt; directly. It resolves a format first:&lt;/p&gt;</description></item><item><title>Security-Scoped URLs</title><link>https://techrawcull.netlify.app/docs/security/</link><pubDate>Thu, 05 Feb 2026 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/docs/security/</guid><description>&lt;h1 id="security-scoped-urls"&gt;Security-Scoped URLs&lt;a class="td-heading-self-link" href="#security-scoped-urls" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;RawCull is a sandboxed macOS app. Any access outside the app container must come from user consent, usually a file/folder picker. RawCull uses two security-scope patterns:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;active catalog access for browsing/culling,&lt;/li&gt;
&lt;li&gt;persistent bookmarks for the rsync copy source and destination.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="source-map"&gt;Source Map&lt;a class="td-heading-self-link" href="#source-map" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Area&lt;/th&gt;
					&lt;th&gt;Files&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Active catalog scope&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;RawCullViewModel.swift&lt;/code&gt;, &lt;code&gt;RawCullViewModel+Catalog.swift&lt;/code&gt;, &lt;code&gt;RawCullApp.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Catalog scan scope&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Actors/ScanFiles.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Copy-folder bookmarks&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Views/CopyFiles/OpencatalogView.swift&lt;/code&gt;, &lt;code&gt;SourceAndDestinationSection.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;rsync runtime scope&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Model/ParametersRsync/ExecuteCopyFiles.swift&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;File writes needing scope&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ExtractAndSaveJPGs.swift&lt;/code&gt;, &lt;code&gt;SaveJPGImage.swift&lt;/code&gt;, rsync workflow&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="api-basics"&gt;API Basics&lt;a class="td-heading-self-link" href="#api-basics" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The core calls are:&lt;/p&gt;</description></item><item><title>About</title><link>https://techrawcull.netlify.app/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/about/</guid><description>&lt;section id="td-cover-block-0" class="row td-cover-block td-cover-block--height-auto js-td-cover td-overlay td-overlay--dark -bg-dark" &gt;
 &lt;div class="col-12"&gt;
 &lt;div class="container td-overlay__inner"&gt;
 &lt;div class="text-center"&gt;
 &lt;h1 class="display-1 mt-0 mt-md-5 pb-4"&gt;About RawCull&lt;/h1&gt;
 &lt;div class="pt-3 lead"&gt;
&lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
&lt;/section&gt;
&lt;div&gt;&lt;a id="td-block-1" class="td-anchor-no-extra-offset"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;section class="row td-box td-box--primary td-box--height-auto"&gt;
&lt;div class="col"&gt;
&lt;div class="container"&gt;
&lt;h2 id="about-rawcull"&gt;About RawCull&lt;a class="td-heading-self-link" href="#about-rawcull" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hello!&lt;/p&gt;
&lt;p&gt;If you have ideas, feedback, or suggestions about RawCull, please reach out to me at &lt;a href="mailto:thomeven@gmail.com"&gt;thomeven@gmail.com&lt;/a&gt;. I&amp;rsquo;d love to hear from you.&lt;/p&gt;
&lt;h3 id="background"&gt;Background&lt;a class="td-heading-self-link" href="#background" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I started RsyncOSX in August 2016 as a way to learn Swift, and after eight years of releases, it was archived in August 2024. RsyncUI, built with SwiftUI, began in late 2020 and continues to be actively developed. RawCull represents my latest venture into building specialized macOS applications with modern Swift technologies.&lt;/p&gt;</description></item><item><title>Search Results</title><link>https://techrawcull.netlify.app/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/search/</guid><description/></item><item><title>Website information</title><link>https://techrawcull.netlify.app/site/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://techrawcull.netlify.app/site/</guid><description>&lt;p&gt;Site built with &lt;a href="https://github.com/google/docsy/releases/v0.16.0"&gt;&lt;span class="badge bg-primary text-bg-primary fs-6"&gt;Docsy
v0.16.0 &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="build-information"&gt;Build information&lt;a class="td-heading-self-link" href="#build-information" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Netlify build information:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Attribute&lt;/th&gt;
					&lt;th&gt;Value&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Netlify built&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Date/time&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
					&lt;td&gt;2026-08-12 13:22 UTC&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ID&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;6a7c73958fba6e000883586a&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Deploy log&lt;/td&gt;
					&lt;td&gt;&lt;a href="https://app.netlify.com/teams/docsy-example/builds/6a7c73958fba6e000883586c"&gt;6a7c73958fba6e000883586c&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Deploy context&lt;/td&gt;
					&lt;td&gt;production&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Commit&lt;/td&gt;
					&lt;td&gt;&lt;a href="https://github.com/google/docsy-example/commit/c736018fef1202208f2e94fb89249a3aa2fd62c0"&gt;@c736018&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Branch&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;main&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;script&gt;
document.addEventListener("DOMContentLoaded", function() {
 var options = { hour: '2-digit', hour12: false, minute: '2-digit', timeZoneName: 'short' };
 var buildDate = new Date("2026-08-12T13:22:47Z");
 document.getElementById("local-time").innerText = buildDate.toLocaleString(undefined, options);
});
&lt;/script&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Approximate build timestamp.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;In your timezone: &lt;span id="local-time"&gt;unknown&lt;/span&gt;.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item></channel></rss>