<feed xmlns='http://www.w3.org/2005/Atom'>
<title>duet/tests/test-duet-safety.el, branch main</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<id>https://git.cjennings.net/duet/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/duet/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/duet/'/>
<updated>2026-06-06T16:37:39+00:00</updated>
<entry>
<title>test: cover the remaining failure, contract, and safety branches</title>
<updated>2026-06-06T16:37:39+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-06T16:37:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/duet/commit/?id=0930ec3c259d93a68fc59854677cdc7fef634e71'/>
<id>urn:sha1:0930ec3c259d93a68fc59854677cdc7fef634e71</id>
<content type='text'>
The bug fixes raised line coverage on duet.el to 92.3%. This closes the rest. The new tests exercise the branches a review would want locked down before execution and UI build on this core: each arm of the minimal failure normalizer (missing executable, stall, signal cancellation, unknown-without-exit), a :match predicate rather than a regexp, the rsync normalizer mapping known stderr to permission/space/protocol classes, the capability-tier contract check, an explicit :async override, the case-collision path through the safety composite's injected predicates, and redaction of a pattern with no capture group.

Line coverage on duet.el is now 100%. The one deliberately trivial case left is the entry command, a not-yet-implemented stub that errors. Its test asserts that and will change when the pane layout lands.
</content>
</entry>
<entry>
<title>feat: add the pure data-safety planner</title>
<updated>2026-06-06T16:34:24+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-06T16:34:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/duet/commit/?id=ef33eefa4cc45f2d80d7ffe27080bf766e9fa999'/>
<id>urn:sha1:ef33eefa4cc45f2d80d7ffe27080bf766e9fa999</id>
<content type='text'>
Phase 3 shipped conflict and move sequencing but skipped the data-safety checks the design spec makes the pure planner's job. This adds them: same-file rejection, dir-into-itself rejection, trailing-slash destination resolution, special-file rejection, symlink surfacing, case-insensitive collision detection, and path-length and reserved-name checks.

Every check is pure. The filesystem facts each one needs (a path's lstat type, the names already at a destination, whether that filesystem folds case, its path-length limit, its reserved names) are injected, so the planner decides before a byte moves and the tests never touch a real file. Each problem is a plist with a class, a severity, the file, and a message. An error severity blocks a transfer, and a warning surfaces a decision, which is how a symlink is carried as follow-versus-preserve rather than silently chosen.

duet--plan-move-safe composes the checks with the move planner: a source carrying a blocking error is skipped with no copy and no delete, a safe source gets a copy and a delete gated on its copy success, and no delete is ever ungated. Coverage on duet.el rises to 92.3%.
</content>
</entry>
</feed>
