diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-17 14:29:01 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-17 14:29:01 +0200 |
| commit | 9ff1297471a483bad1b2b38ccb1e42614f60fc5e (patch) | |
| tree | 687aef6a655be777ea2dc365ced62a1667d59294 /CHANGELOG.md | |
| parent | 40dbf18893c33bc40c8617d0f3e8de16ce2947e2 (diff) | |
| download | krino-8743885db03025b3ad7748f324266d1a8f19f644.tar.gz krino-8743885db03025b3ad7748f324266d1a8f19f644.zip | |
Diffstat (limited to 'CHANGELOG.md')
| -rw-r--r-- | CHANGELOG.md | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e4dd69..ccb2a62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,85 @@ ## Unreleased +## 0.0.12 — 2026-09-17 + +Published, and reviewed. The repository is at +`https://git.labunix.xyz/krino.git` and the module path is +`git.labunix.xyz/krino`, so `go install git.labunix.xyz/krino/cmd/krino@latest` +works from this release on. Then five reviews — security, correctness, +determinism, performance and the window — found four high-severity defects +and a number of smaller ones; what follows is what they found and what was +done about it, each with the measurement or the test that settles it. + +**Files that could have been lost** + +- A symlink planted in the directory being sorted, named after a rule's + destination, redirected a move or a copy out of the tree — and under + `(on-conflict overwrite)` trashed a file *outside* it — while the plan the + user approved showed only the in-tree text. A step whose destination + passes through a symlink at or below the sorted directory now fails. A + destination the configuration itself names outside that directory, `~/docs` + on another disk say, is the user's own arrangement and is followed as + before. +- A file trashed to make room was logged only when the step that needed its + name had finished — for a copy, the whole data transfer later. Killed in + that window, krino reported "nothing applied" while the user's file sat in + the Trash. It is now logged the moment it is trashed, and a displace that + cannot be logged fails the step. +- A chain ending in `(delete permanent)` never gave back the file it had + displaced: the walk stopped at the delete, so the user's only copy stayed + in the Trash and `krino log` called the run undone. The displaced file is + offered as its own entry in the undo plan. +- A `(duplicate)` test written in an `(exclude ...)` bought no protection at + all: a later rule permanently deleted every copy. Duplicate scopes are now + collected from excludes as well as rules. +- The window could release the directory lock and close the log under a + running Apply — by saving rules, saving settings, adding a directory or + closing the window — so a file moved that no `krino undo` could see. The + tabs refuse to close while their apply is in flight. +- Deleting one of two forms written on the same line deleted both, and + clearing a setting took whatever else shared its line — including the + closing paren of `(defaults ...)`, which broke the file the Settings + window had just written. Both take a whole line only when the line holds + nothing else. + +**The directory lock is now the kernel's.** `flock(2)` on the lock file +replaces "write my pid, and judge whether the pid in the file is still +alive". A crashed run's lock is released by the kernel, so there is no stale +lock to detect and no takeover to race over: two runs could previously both +decide a lock was stale and both take it. A pid reused after a crash no +longer wedges a directory for ever, and a run that waits for a lock says so +before it waits. + +**Faster, measured on invented corpora** + +- A content class is worked out once instead of once per copy: 2000 + identical files, 1.89s → 0.58s, with byte-identical plans. +- The search for a free `stem_N` continues instead of starting again at + `_1`: 1500 files renamed onto one name, 2.63s → 0.05s. +- A file's name is folded once rather than once per name test: 4000 names + with diacritics over twelve rules, 0.33s → 0.13s. +- `max-read` now bounds what a file *becomes*, not only what is read, and + large extractions are rationed: twelve 40 MB files, peak memory 3294 MB → + 728 MB. Small files are untouched. + +**Other** + +- `{now:FMT}` is the start of the run, as the spec always said, rather than + the moment each directory happened to be planned — so a long review cannot + split one run's output across two folders, or two dates. +- The Settings window's sort order, column toggles and preview height were + read but never connected to anything; they work now, and changing a + setting no longer discards the divider positions. +- "Keep this copy, replace the other" refuses a second file aimed at the + same place, which the engine has always refused to plan. +- `About`, at the foot of Settings: the version, the licence, the author and + the repository. +- The Plan tab's toolbar reads in the order the work happens, and `Scan` + carries the theme's accent. +- Comments that cited the development process rather than the code are + rewritten; the README is a third shorter, with a screenshot. + ## 0.0.11 — 2026-09-17 The window, worked over from a fortnight's worth of using it: the plan reads |
