summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 23:39:37 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 23:39:37 +0200
commitc09020c2fb01da24d5befbed78ce3b73b5efbe4c (patch)
tree8cd1086588988fafaf238aed8a38a7ec85b0afa3 /docs
parent3990586a85e91923c0a3ae1a1f0f61420db555ac (diff)
downloadkrino-c09020c2fb01da24d5befbed78ce3b73b5efbe4c.tar.gz
krino-c09020c2fb01da24d5befbed78ce3b73b5efbe4c.zip
content tests are three-valued: unknown when unreadable or read in part
Diffstat (limited to 'docs')
-rw-r--r--docs/design.md26
1 files changed, 18 insertions, 8 deletions
diff --git a/docs/design.md b/docs/design.md
index 35b0de0..4196894 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -199,10 +199,12 @@ as "excluded" in the plan, listed with the form that matched under `-v`,
and traced by `explain`; `check` lists every directory's exclusions. Since
no rule has run yet, `(matched)` is never true inside an exclude.
-An exclude fails closed: when evaluating it reaches a content test that
+An exclude fails closed: when its value depends on a content test that
cannot read the file (over `max-read`, a tool missing, failing or timing
-out), the exclude holds, and the file is set aside as "(content
-unreadable)" with the warning. A file whose format has no text at all (an
+out, or a document read only in part), the exclude holds, and the file is
+set aside as "(content unreadable)" with the warning (§5.4 rule 4). One that
+is false whatever the text holds, such as `(exclude (content "x") (type
+txt))` on a pdf, does not. A file whose format has no text at all (an
image, an archive) is not unreadable: it contains no keyword, so its
content tests are simply false and raise no warning. So is a file of no
known extension that starts as text and holds binary data further on, such
@@ -258,10 +260,16 @@ UTF-8 is replaced by U+FFFD before folding.
cheapest first: `type`, `size`, `age` and `matched`, then `name` and
`path`, then `duplicate`, then `content`. Content is extracted at most once per file,
and only if evaluation reaches a `content` test.
-4. If a file's text cannot be extracted, `content` is false and the plan
- shows a warning naming the rule that wanted it. A format with no text
- (§6, "anything else") is not a failure: `content` is false, silently. Inside an `exclude` the
- whole exclude then holds instead (§4.6).
+4. If a file's text cannot be extracted, `content` is **unknown** and the
+ plan shows a warning naming the rule that wanted it. A document read only
+ in part (an archive entry that would not open) answers a keyword found in
+ what was read; one not found is unknown. `and`, `or` and `not` combine
+ unknowns by three-valued (Kleene) logic: `and` is false if any argument is
+ false, `or` true if any is true, `not` of unknown is unknown, so an
+ unknown only reaches the top where the text could change the answer. A
+ rule matches only when its condition is true; an unknown exclude holds
+ (§4.6). `explain` shows an unknown test as `?`. A format with no text (§6,
+ "anything else") is not a failure: `content` is false, silently.
### 5.5 Duplicates
@@ -896,7 +904,9 @@ What that means, and the tests that hold it (plans 8 and 9):
- Undo restores a trash entry only while it is still the file the run put
there (size, mtime, recorded path), re-checks every file at execution
time, and can finish an undo that stopped part way.
-- An exclude whose content test cannot read the file holds (fails closed).
+- An exclude whose value depends on a content test that cannot read the
+ file holds (fails closed); a rule whose value does is not matched, so
+ `(not (content "x"))` never acts on a file krino could not read.
- A file reaches an external tool only as an absolute path, so a name
starting with `-` is never read as an option.
- A trash entry name from the log must be a plain name inside the Trash,