chadtmiller.com/knotless
git that lives in your Atmosphere account
A private repository's records are named in full, and public-form references are moved
MergedThis pull rewrites an account's own space records to full-form references the first time knotless writes there for them, and migrates the appview index once, counting the records still holding public-form references. I read crates/knotless/src/short_form.rs and crates/knotless-serve/src/index/short_form.rs in full and found nothing that must change.
- Client side: the guard against re-entry is sound. The in-process
MOVEDset stopsapplyfrom callingmove_onceagain, and a failure removes the key so the next write retries. Writes that land before a failed chunk are rewritten harmlessly on the retry. - Index side: the one-time move is safe to re-run after a crash. A record already moved finds no value under its short URI, so it falls to the rename path, which does nothing.
I did not read the other 2,300 or so lines of the diff, which carry the stacked pull's commits and the docs and changeset edits. I also did not confirm the docs paragraph in docs/design/access.md that AGENTS.md asks for. All seven checks were still queued when I looked, so the coverage gate, the lexicons check and the plans check are unverified. Make sure test passes, in particular the plans check on the new space_record_key index and the two scans: statements, before merging.
Carried forward: the change this pull makes at 3b15d2e7f20f94acc672ea07aea1a405b4ae393d is the one reviewed at 7ab66e78f38a4a02a5b6ff795546cfb697f5a8d5, so that review stands. What is new comes from its base.
This pull moves an account's own space records to full-form references the first time knotless writes there for them. It also migrates the appview index once and counts the records that still hold public-form references. My round 1 review asked for the test check to pass, in particular the plans check, and that is not yet shown. I found nothing in the code that must change.
- Earlier failure: the
testcheck on the previous head, 3b15d2e, failed.references_in_the_public_form_in_a_space_are_moved_oncepanicked atlibrary.rs:1099withSome(0)instead ofNone. Thee2echeck also failed on 3b15d2e at itsflowsstep. I didn't read its log, so I don't know why. - Latest commit: a14f6d4, "A space that cannot be read is moved the next time, as the test shows", reworks that test. The unreadable-space case now uses a separate private repository and a mock server that answers 500. It asserts
move_oncereturnsNoneand that the cache note is not written. The test reads correctly to me. - Checks on a14f6d4: all seven are still queued, so nothing yet confirms the fix or that
e2enow passes. The plans check on the newspace_record_keyindex and thescans:statements is also still unverified; it was skipped on the failed run.
Do not merge until test and e2e are green on a14f6d4. Re-run e2e if it fails again and look at the log, since I can't tell whether this pull caused that failure.
This round's only change is 00c0bc7, "The index's move counts every line it runs". It is a behaviour-preserving refactor of crates/knotless-serve/src/index/short_form.rs. The NOTED and DONE SQL strings become constants. The reaction subject update now always runs, with coalesce(?2, subject) leaving the subject alone when there is none. That is equivalent to the old if let, and I found nothing wrong with it.
My earlier request still stands: test and e2e must pass on this head before merging. Only the docs check has finished (success). check and e2e are running, and test, web, shots and lexicons are still queued. The test run covers the fixed references_in_the_public_form_in_a_space_are_moved_once and the plans check on space_record_key. Nothing has confirmed either yet. If e2e fails again, read its log.
This pull lands A private repository's records are named by their URI in its space with it, whose commits are the first here, so the two land as one.
What changes
A private repository's records are named in full. A record in its space is named
at://<owner>/space/dev.knotless.space/<name>/<author>/<collection>/<rkey>wherever knotless gives one: the entriesTargetreads from the space, what a write returns (knotless pull,issue,comment,rerun), a runner's check URIs and a queue's failed checks, a repository's reference (Target::reference, and knotless-serve'sRepo::reference/uri), and the references new records hold (a comment'ssubject, a check'spull, a state'ssubject).Remote::uri_ofmints them;Remote::space_refis the space.Typed input in the public form still works.
Target::namedgives a URI in the public form the space of the repository it is about; every entry point that takes a record's URI calls it (show, comment, label, hide, set_state, merge, compare, pull_diff, retarget, edit/delete, react, enqueue, leave, revert, mergeable,rerun --pull). knotless-serve'sRepo::nameddoes the same where its handlers look up a record (getThread, getCheck, getAttachment, reactions, hides).queue::standingand thechecks --pullfilter compare withaturi::same.Records written before are read as ever.
crates/knotless/src/short_form.rsgives a reference in the public form the space it was read from, in the fields that name another record of the same space (subject,subject.uri,pull,reply,review,reverts,check,batch[].pull,checks[].check), on every recordRemotereads from a space and every record the index takes in from one. Typed text, as a body'sFixes, is not touched.The index keys space records by their full URI.
put_at/delete_atkey a record from a space in full;read_of,maybe_memberandPURGEbuild the full URI fromspace_record; a pull'shead.repo.uriin the public form is given the space the index keeps that repository's record in (new indexspace_record_key).Index::repofinds a repository by either form.recordOfinweb/src/lib/format.tsreads either form.Records an account wrote are moved to the full form, once.
knotless::short_form::move_onceruns fromTarget::mine(every forge write: CLI, MCP, pages, the review and triage bots) and from knotless-run'sReporter::mine. The first time knotless writes into a space for an account, it lists that account's records there as written (Remote::list_as_written), gives each public-form reference inshort_form::FIELDSthe space, gives a pull'shead.repo.urithe space of its head repository when that is private, and writes back those that changed through the account's own session or delegation, ten to anapplyWrites. Done, it notes<did> <space>in the cache (short-form-moved) and logsshort-form references moved; a failure is logged and tried again next time, and never fails the write it rides on. Bodies and other typed text are left as written.The appview's index is moved once, and counts what is left.
crates/knotless-serve/src/index/short_form.rs: as the index opens, everyspace_recordrow is moved from its public-form URI to the full one, noted inshort_form_movedand not run again.put_atnotes inshort_form(uri, author)each record from a space whose author wrote a public-form reference, and drops it when that record is written again in full or deleted. Each start logsshort-form references leftper author and in all;Index::short_form_leftgives the same.Why
A private repository's records named in the public form lose the space they are in, can name two records in two spaces alike, and 404 at the author's PDS (
repo.getRecord), as at://did:plc:bcgltzqazw5tb6k2g3ttenbj/dev.knotless.pull/3mzbv3emkc72b in hetzner-infra does. Proposal 0016 names them with every segment through the rkey. Reading public-form references as they come would leave them in people's records for ever, so they are moved, through the authors' own access since nobody else can write their records, and counted so the reading side can go.All the moving is in the two
short_formmodules behind one entry point each, so removing it is one small pull: onceshort-form references left in alllogs 0, delete both modules,Remote::list_as_written, the resolve inRemote::parse, the twomove_oncecalls, the index's three calls andTABLESentry, and the docs paragraph.aturi::resolvestays: typed text never moves.How it was checked
Unit tests:
short_form(each field, lists and objects, what is left),index::records_in_a_space_are_kept_by_their_full_uri,index::short_form::an_index_from_before_is_moved_once(an index as the previous release kept it, opened again: keys, comment subject, reaction, push, head repository, the count by author, once only, the count falling), andreferences_in_the_public_form_in_a_space_are_moved_once(library, spaces alpha: subject and head in full, body untouched, the cache noted, not again, nothing for a public repository, an unreadable space left to try again). The private flows over the spaces alpha intestande2erun the rest.Shortcomings
forkOf,transfer, a star's subject) keeps the form it was written in: readers match it by owner and key.Changesets:
.changeset/space-record-uris-full.md,.changeset/space-short-form-moved.md.🤖 Generated with Claude Code