core before UI - #68
Merged
Merged
Conversation
The mockup lists everything a card shows; the store only gave five of those fields. `Listed` now carries app, label, colour, thumbnail, paste count, last use, creation and breakage, and `list` returns a `Page` with an opaque cursor keyed on the order so paging never repeats or skips under ties. `facets` counts the classes within the current search and `distinct_apps` the source applications. `Filter` grows exclusion of classes and applications, application equality on the folded column, `since` on `modified_at` (a recopy is a copy), broken hidden by default and askable, a label-scoped query and three indexed orders. `parse` turns `token @code ~1h` into a `Filter` through one table of keys and symbols, treating a prefix as an operator only when its value is known. Searching marks the fragment that matched, cut from the text as it was copied: `search::excerpt` maps folded matches back to the original bytes and says whether it hit the text, the label, the application or what was read inside an image. Folding no longer allocates per character — 64 KB in 0.05 ms instead of 2.6 — which is what makes a snippet per row affordable. `sweep` applies a `Policy` in one pass — broken past their grace, expired, beyond a count, beyond a byte quota, blob files nobody references — and checkpoints once. Purging a broken item releases its blobs; `update_text` edits in place, drops the renderings that no longer match and checkpoints so the old text does not stay readable in the database or its log; `mark_present` undoes `mark_broken`. The blob sweep only touches digest-shaped names and reclaiming a blob refreshes its mtime. Schema version 2 rebuilds the ordering indexes that gained an `id` tiebreaker. `paste_as` takes a neutral `Content` and answers `forms_for` and `render`: JSON pretty, minified, keys and TSV table; colour as hex, rgb and hsl with alpha; link as Markdown, domain or with its title; code as one line, a fenced block or dedented; token as an Authorization header, a curl or the decoded JWT claims; image as JPEG on white or as its OCR text; files as paths; rich text as Markdown through a small HTML converter. `Kind::Token` is the fifteenth class: a JWT or a known prefix, no long-hex heuristic. `serde_json` joins the core. `watch::insist` retries a too-slow source five times with 150 ms between attempts and gives up as soon as the change count moves; `cp_mac::capture::capture_insisting` wires it and probe C6 checks a source that answers costs no pause. macOS builds the `Content` from its formats and restores the synthetic ones the store writes, the way Windows already did. Windows takes the rest in its own session.
The HTML-to-Markdown scanner sliced at byte one, so any rich copy whose text after a tag began with an accented letter panicked; it now advances by characters, gives up on a `<` with no `>` left in one pass instead of rescanning per bracket, respects comments and quoted attributes, and never slices before the start of an anchor whose surroundings were trimmed inside `<pre>`. `dedent` strips the whitespace prefix every line shares, character by character, instead of a byte count that could land inside a non-breaking space. The curl form escapes single quotes: a JWT signature may carry any character, and the rendered line is meant for a shell. Percentages in rgb channels and in alpha are scaled. Quotes keep every paragraph; fences outgrow the backticks inside; odd URLs go in angle brackets. `Form::AsIs` is gone — pasting the original item is the interface's job — and every form `forms_for` offers now renders, which a test asserts over ten contents. `capture_insisting` no longer spawns a reader per attempt: `reading::begin` hands back a `Pending` that can be waited on more than once, so a late answer from Excel is collected instead of queued behind a fresh read, and a hung source blocks one thread rather than five. Probe C6 allows a legitimate attempt to take up to `PATIENCE`.
…rter `cp_mac_sys::files::open` hands a file to its application and `reveal` selects it in the Finder — the two card actions the mockup draws that the core could do without a window. Probe M1 and M2 watch the Finder and TextEdit come to the front through System Events, because `NSWorkspace.frontmostApplication` in a command-line process reports a dead application with pid -1 when the screen is locked; `frontmost()` now returns nothing for such a pid instead of a destination nobody can paste into. Two copies from Vivaldi taught the HTML converter what Google writes: everything is wrapped in a `<b style="font-weight:normal">` that is not bold, real bold and italic live in `font-weight` and `font-style` on spans, and a Sheets range is a `<table>`. Inline markers now come from the tag and its style through one stack, so a stray close is ignored, and a table renders as a Markdown table with a header rule, cells joined on one line and pipes escaped.
…the branch Safari offers an image as TIFF only, never PNG: `Content.image` now takes any decodable bytes, so a picture copied from a web page can be pasted as JPEG and read by OCR. Safari also attaches a 2.5 MB web archive to a 43 KB logo; the catalog gains `page_archives`, and `decide_in` notes them as presence when the family is Image, the same shape as the Finder icon rule. Windows declares no page archives. A Pages table and a Sheets range in Safari confirmed the rest: iWork markers stay presence, the empty PNG stays absent, the Markdown table keeps its header rule. The whole branch then went through five lenses at once, and the sum showed what the pairs had not. FTS5 with external content keeps the terms of a deleted row in its segments until a merge: a password copied and erased stayed readable in `history.db` with the WAL at zero. The index now runs with `secure-delete`, schema version 3 optimizes and checkpoints existing databases, and the residue tests look for every token instead of a hyphenated phrase the tokenizer splits. The Markdown writer kept byte offsets for the open link, cell and quote that a later truncation left inside an `é` or past the end; `truncate_to` clamps all three, quotes nest, italics parse `font-style: italic`, attributes match only after whitespace, adjacent bold runs merge, 84 Latin-1 entities decode, and code fences carry no inline markers. `list` with a query sorted whole rows, preview text included; it now sorts `(key, id)` in a subquery and joins the wide columns for the page that survives: 143 → 45 ms on the worst query over 50 000 items, and no temporary B-tree in any order, which the plan test now checks against the real SQL. `blob_is_shared` scanned `item_formats` per released blob, so a byte-quota sweep took thirty seconds; `formats_by_blob` and one transaction per eviction bring it to three. Partial covering indexes make `facets` and `distinct_apps` cost milliseconds; `count` is a difference of two indexes and no longer counts broken rows; `count_matching` and `distinct_apps` take the filter. `checkpoint` reports whether it truncated, interactive deletes wait fifty milliseconds instead of five seconds, the capture connection runs without autocheckpoint and `checkpoint_passive` is for whoever cleans up. Previews are capped at 64 KiB on write and 2 000 characters on read; `insert_text` classifies and refuses what `placement` refuses. `update_text` and `insert_item` are transactions, and a released blob respects the same sixty-second grace as the sweep so a capture writing the same digest on another connection cannot lose it. Partial files are private per writer, `remove_at` zeroes in place before unlinking, and a symlink named like a digest is unlinked, never followed. `migrate` runs in one transaction and rebuilds the ordering indexes whenever they are stale, not only from version one. For the interface: `Content` borrows through `Cow`, so Windows can hand over UTF-16 text; `Rendered::into_item` gives every form a paste path with `SYNTHETIC_JPEG` mapped to `public.jpeg`; `Store::item` rebuilds an item; `Cursor` carries its order, is refused under another one, and encodes to text; a query made only of operator symbols is no query; `set_pinned`, `set_thumb`, `label_query`, `Form::ALL`, `FoundIn`. The old `search` family is gone and `budget` measures `list`. `files::open` reveals an executable instead of launching it; `path_of` lives in `files` and `resolved_file_url` says what it returns. Excerpts keep a combining mark or a skin tone with its base. The probe's M1 and M2 skip instead of failing when an app will not come to the front, watch osascript with a three-second guard, and clean their scratch on drop.
The OCR is kept as read: `ocr_text` sits next to the folded `search_ocr` in schema version four, added by `ALTER TABLE` when a database lacks it, so the excerpt found inside an image and the "paste as text read" form show `Pedido AB-4417` and not `pedido ab-4417`. Deleting and editing clear both columns; an OCR that arrives after the delete revives nothing; a version-three database keeps showing its folded text until the image is read again. `Form::ColorName` pastes the CSS name of a colour: exact when there is one, the nearest of 139 when it is within a redmean distance of 30, and not offered at all when no name is honestly that colour or when the colour carries alpha. Where two names share a value the common spelling wins. Integer arithmetic, no floats, and a test per scenario. `cp_core::capture::Captured` is the one enum for both platforms, with `Kept`, `Refused`, `Nothing`, `TooSlow` and `Superseded`, and the `insisting` adapter beside it. On macOS `capture` now says why it did not keep: the refusal and its marker, an empty pasteboard, or a change count that moved mid-read. Windows drops its own enum for the shared one; `clippy -D warnings` passes for the Windows target from here. Pasting as plain text is one path like every other form: `render`, `into_item`, `to_pasteboard`. The stored item keeps its rich formats, which probe I5 checks by restoring it afterwards. Copying the same thing twice was two items from four of six sources, measured with the new `twice` example: Docs writes a fresh `docs-internal-guid` in its HTML on every copy, Word rotates the `\rsid` of its RTF and the `applewebdata://` UUID of its web archive, Pages and Numbers stamp a date inside the RTFD, Excel rotates the web archive UUID; only Sheets was stable on its own. The identity now drops the variable part of that GUID from markup, and renderings — RTF, RTFD, web archive, PDF — carry no identity when a primary format is present; a copy that is only a rendering keeps one of its own. Rich and plain stay two items: the identity is still what would be pasted. All six sources now give one fingerprint for two copies. The symlink test builds on Windows through `symlink_file`, and the probe bodies are formatted the way the CI step checks them.
The Windows mutants job mutated cp-core, cp-store and cp-win in one sixty-minute slot and was cancelled at the hour twice on this branch, while macOS finished in fifty-two. It now runs as two shards of the same set, and every workflow cancels the run a newer push superseded instead of spending the hour on a commit nobody will merge.
rgdevment
force-pushed
the
rgdevment/core-before-ui
branch
from
September 21, 2026 12:53
8d0e3e5 to
6ab971e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.