Repository navigation
Description publication: lock, base SHA, symlink refusal, transitions, records (Stage 1, PR 5) - #188
Merged
Merged
Conversation
…ions, records Stage 1 design PR 5: read_description(path) with R_FILE_SYMLINK, the R_* comparison of a candidate with the published file (transitions t01-t12), and publish_description under the output lock with the base SHA-256 check and the append-only morphobricks.records.jsonl. Not used by any run yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Scma6W3LC11s3qjXHZuGDm
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Scma6W3LC11s3qjXHZuGDm
This was referenced Nov 7, 2026
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.
Stacked on #187 (the writer, which publication needs): this branch contains #187's commit
f71982b, so until #187 merges the diff shows both. The new work is the single commitbf868b2. Independent of #186 (they will conflict only in the CHANGELOG head).What changed
Design PR 5 (section 3 lifecycle step 2, section 5 row 5) plus owner answer Q2 (records file, now normative in Spec experiment-v1 4.6). All additive; no run, notebook or CLI uses it.
description_file.read_description(path) -> Description: reads the bytes once, refuses a symbolic link (R_FILE_SYMLINK, also a dangling one; opened withO_NOFOLLOW), then the strict reader. A refusal is aDescriptionErrorcarrying every issue of the first failing phase (phase0 for the file itself).description_transition: everyR_*that applies to a candidate offered over the published file, as a set:R_CONFIRMED_ID_CHANGED(4.6 a, b, b2, c),R_USED_ID_DROPPED,R_USED_ID_REUSED(4.9),R_CONFIRMED_ON_CHANGED(4.4a).Reconfirmation(kind, old_id, new_id, confirmed_on)is the user's recorded acceptance; it accepts only the exact change it names, never a used-ID or date refusal, andconfirmed_onis required (no default).run/description_file.publish_description(folder, candidate, base_sha256=..., confirmations=...), underoutput_lock: refuse a symlinked file or records file; baseNoneor malformed isR_DRAFT_BASE_MISSING; base differing from the SHA-256 of the file on disk (orabsentvs a file that appeared) isR_PUBLISHED_FILE_CHANGED; canonical bytes are re-read by the strict reader; transitions; then atomic write. Every refusal writes nothing. A re-confirmation the candidate does not need is aValueError, not silently recorded.morphobricks.records.jsonl(one JSON object per line:type,id_kind,old_id,new_id,confirmed_on,old_sha256,new_sha256),O_APPENDplusfsync, never rewritten or truncated; a torn or non-JSON records file refuses before anything is written. If the append fails after the file was replaced, the previous file is restored (or removed for a first publication).read_records(folder)returns the rows for the next run to copy.Refusalenum (theR_*codes above) added todescription_rules.py, the one table; a test checks each is in Spec section 8. Layers, CHANGELOG, AGENTS.md repo map updated.Decisions and deviations to review
confirmed_onand image counts. Spec 10 says new FOVs in an existing unit do not reopen a confirmation, so a newconfirmed_onbeside only a changedimage_countisR_CONFIRMED_ON_CHANGEDhere. The Spec'srefval.transitiontreats an image-count change as reopening and accepts it. The oracle cross-check therefore compares with everyimage_countnormalised to 1, and the difference has its own test. This may deserve a sentence in the Spec.Reconfirmation(P20's removal of DrugA from v01 needs five). The UI will batch them; the records stay one per entity. This follows the text and the oracle.base_sha256field (design PR 7), the physical checks and derivedexperiment_design.csv(PRs 8, 10), and copying the records into the run manifest (PR 11).publish_descriptiontakes the base as an argument.Tests
tests/test_spec_transitions.py(70): t01-t12 each give exactly their listed set (t06 none); every ordered pair of the 48 valid and transition fixtures agrees with the Spec's oracle (with decision 1); a re-confirmation accepts only the change it names.tests/test_spec_publication.py(20): P16 (t01/t02 refused, t01 accepted only with records,v16accepted with unchanged digests), P17 (second draft refused withR_PUBLISHED_FILE_CHANGED, published bytes stay the first's, re-derived draft accepted), P18 (appeared file, six unusable bases), P19 (including the returning DrugA folder), P20 (dropped ID; removal accepted with the ID kept inused_ids), P22 (date byte-identical,t05refused, accepted after a reopening).tests/test_description_file.py(21): P09 (symlink and dangling symlink refused by reader and by publication, link untouched), held lock, records append-only, torn and symlinked records file, failed append restores, invalid candidate or published file.Result on the old code: none of the modules exist on
main, so the new test modules fail at collection (ImportError).Checks
python tools/check.py: 3791 passed, 4 skipped (case-insensitive file system x3, file-mode permissions x1; none are Spec tests), 2 warnings; Ruff and code rules clean. Symlink tests skip only where the system forbids symbolic links (not the case here, they ran).🤖 Generated with Claude Code
https://claude.ai/code/session_01Scma6W3LC11s3qjXHZuGDm