sieve-tray 0.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. sieve_tray-0.9.1/LICENSE +21 -0
  2. sieve_tray-0.9.1/PKG-INFO +367 -0
  3. sieve_tray-0.9.1/README.md +350 -0
  4. sieve_tray-0.9.1/pyproject.toml +32 -0
  5. sieve_tray-0.9.1/setup.cfg +4 -0
  6. sieve_tray-0.9.1/sieve_redact.py +1209 -0
  7. sieve_tray-0.9.1/sieve_tray.egg-info/PKG-INFO +367 -0
  8. sieve_tray-0.9.1/sieve_tray.egg-info/SOURCES.txt +29 -0
  9. sieve_tray-0.9.1/sieve_tray.egg-info/dependency_links.txt +1 -0
  10. sieve_tray-0.9.1/sieve_tray.egg-info/entry_points.txt +3 -0
  11. sieve_tray-0.9.1/sieve_tray.egg-info/requires.txt +7 -0
  12. sieve_tray-0.9.1/sieve_tray.egg-info/top_level.txt +5 -0
  13. sieve_tray-0.9.1/sieve_tray.py +878 -0
  14. sieve_tray-0.9.1/sieve_tray_gui.py +1495 -0
  15. sieve_tray-0.9.1/sieve_tray_i18n.py +385 -0
  16. sieve_tray-0.9.1/sieve_tray_storage.py +264 -0
  17. sieve_tray-0.9.1/tests/test_image_canvas.py +123 -0
  18. sieve_tray-0.9.1/tests/test_image_editor.py +140 -0
  19. sieve_tray-0.9.1/tests/test_image_editor_sizing.py +48 -0
  20. sieve_tray-0.9.1/tests/test_image_entry.py +93 -0
  21. sieve_tray-0.9.1/tests/test_image_sanitize.py +149 -0
  22. sieve_tray-0.9.1/tests/test_image_tree_gui.py +107 -0
  23. sieve_tray-0.9.1/tests/test_image_tree_sanitize.py +237 -0
  24. sieve_tray-0.9.1/tests/test_redact_vendor_sync.py +26 -0
  25. sieve_tray-0.9.1/tests/test_sanitize_history_ui.py +166 -0
  26. sieve_tray-0.9.1/tests/test_sanitize_thread_affinity.py +120 -0
  27. sieve_tray-0.9.1/tests/test_sieve_tray.py +88 -0
  28. sieve_tray-0.9.1/tests/test_sieve_tray_audit.py +320 -0
  29. sieve_tray-0.9.1/tests/test_sieve_tray_i18n.py +55 -0
  30. sieve_tray-0.9.1/tests/test_sieve_tray_sanitize.py +191 -0
  31. sieve_tray-0.9.1/tests/test_sieve_tray_storage.py +168 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kai IWASAKI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,367 @@
1
+ Metadata-Version: 2.4
2
+ Name: sieve-tray
3
+ Version: 0.9.1
4
+ Summary: A general-purpose observation tool combining Sieve Lens, Sieve Scope, and Sieve Referee
5
+ Author: Kai IWASAKI
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: sieve-lens>=0.10.0
11
+ Requires-Dist: sieve-scope>=1.3.0
12
+ Requires-Dist: sieve-referee>=1.3.0
13
+ Provides-Extra: gui
14
+ Requires-Dist: PySide6>=6.5; extra == "gui"
15
+ Requires-Dist: Pillow>=10.0; extra == "gui"
16
+ Dynamic: license-file
17
+
18
+ **English** | [日本語](README.ja.md)
19
+
20
+ # Sieve Tray v0.9.1
21
+
22
+ **A general-purpose observation tool — a desktop front-end for the Sieve series**
23
+
24
+ > Combines [Sieve Lens](https://github.com/neguseatama/sieve-lens)'s invisible-content
25
+ > observation, [Sieve Scope](https://github.com/neguseatama/sieve-scope)'s code
26
+ > similarity detection, and [Sieve Referee](https://github.com/neguseatama/sieve-referee)'s
27
+ > text paraphrase detection — plus, new in v0.8.0, Sieve Referee's quantifier
28
+ > audit lane — into a single desktop app. Point it at a folder of
29
+ > submissions and it detects and reports, in one pass, documents containing
30
+ > invisible content or hidden prompts, code pairs with suspicious structural
31
+ > similarity, text pairs that look paraphrased or reused, and sentences that
32
+ > make ungrounded universal claims (hallucination candidates).
33
+
34
+ [![Test](https://github.com/neguseatama/sieve-tray/actions/workflows/test.yml/badge.svg)](https://github.com/neguseatama/sieve-tray/actions/workflows/test.yml)
35
+ [![Release](https://github.com/neguseatama/sieve-tray/actions/workflows/release.yml/badge.svg)](https://github.com/neguseatama/sieve-tray/actions/workflows/release.yml)
36
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
37
+ [![Python Version](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/)
38
+
39
+ ---
40
+
41
+ ## 💡 Concept
42
+
43
+ [Sieve Lens](https://github.com/neguseatama/sieve-lens) answers "does this
44
+ document contain something a human can't see but a parser can?".
45
+ [Sieve Scope](https://github.com/neguseatama/sieve-scope) answers "do these two
46
+ source files share suspiciously similar logic, beyond coincidence?".
47
+ [Sieve Referee](https://github.com/neguseatama/sieve-referee) answers "does
48
+ this text say the same thing as that one, just reworded?". All three are
49
+ zero-dependency, deterministic observation engines in the Sieve series — but
50
+ checking a folder of submissions by hand meant running separate tools and
51
+ cross-referencing the output yourself.
52
+
53
+ **Sieve Tray** removes that step. Point it at a directory containing one
54
+ subfolder per submission, and it automatically routes each file to the right
55
+ engine: documents go to Sieve Lens, `.py` files go to Sieve Scope's pairwise
56
+ comparison, and plain-text files (`.txt`/`.md`) additionally go to Sieve
57
+ Referee's pairwise paraphrase comparison **and** Sieve Referee's quantifier
58
+ audit lane (new in v0.8.0, powered by Sieve Referee >=1.3.0). Results land in
59
+ a single window, with local history so nothing has to be re-run, and a detail
60
+ view showing exactly which observation axis fired and why — never a bare
61
+ verdict, only what the underlying engines actually observed.
62
+
63
+ > Like the rest of the Sieve series, this is an **observation tool, not a
64
+ > judgment tool**. A flagged item means "this deserves a human look", not
65
+ > "this is confirmed misconduct".
66
+
67
+ ---
68
+
69
+ ## 🧩 The Sieve Series
70
+
71
+ Sieve is a family of deterministic, zero-dependency engines that share
72
+ the same design principles (deterministic output, no telemetry, fully
73
+ local) — each engine observes or masks one specific risk, and they
74
+ compose:
75
+
76
+ | Package | Role | Connects to |
77
+ |---------|------|-------------|
78
+ | [sieve-core-engine](https://github.com/neguseatama/sieve-core) | Base logic / plugin host for the ecosystem | — |
79
+ | [sieve-lens](https://github.com/neguseatama/sieve-lens) | Observes invisible content & hidden prompts in documents | → redact via `--from-lens` |
80
+ | [sieve-scope](https://github.com/neguseatama/sieve-scope) | Detects structurally similar code pairs | — |
81
+ | [sieve-referee](https://github.com/neguseatama/sieve-referee) | Detects paraphrased / reused text pairs | — |
82
+ | [sieve-redact](https://github.com/neguseatama/sieve-redact) | Masks sensitive regions (text & PNG) with receipts | ← lens, → tray |
83
+ | [sieve-tray](https://github.com/neguseatama/sieve-tray) | Desktop front-end that routes files to the right engine | ← all engines |
84
+
85
+ Observation → masking in one pass: Lens finds what a human can't see,
86
+ Redact removes it with a receipt that proves nothing else changed.
87
+
88
+ ## 🔥 Key Features
89
+
90
+ - **One folder in, everything checked** — routes `.py` files to Sieve Scope,
91
+ plain-text files (`.txt`, `.md`) additionally to Sieve Referee (both pairwise
92
+ paraphrase comparison **and** the quantifier audit lane), and all
93
+ documents (including `.html`, `.docx`, `.pdf`, images) to Sieve Lens,
94
+ automatically, by extension.
95
+ - **Background-threaded GUI** — scanning never freezes the window, even on
96
+ large submission sets.
97
+ - **English and Japanese UI** — switch languages from the Settings dialog
98
+ (English by default). Note: Sieve Referee's own explanation text for a
99
+ flagged text pair is generated in Japanese regardless of UI language,
100
+ since the engine's calibration is Japanese-specific; the detail dialog
101
+ shows it labeled as such.
102
+ - **Sortable, filterable results** — click any column to sort; filter
103
+ documents by filename and/or "flagged only"; filter code/text pairs by
104
+ filename.
105
+ - **Detail dialog** — double-click any row to see the per-axis observation
106
+ states and the underlying evidence/scores/reason the engine recorded, not
107
+ just the mask string.
108
+ - **Quantifier Audit lane (new in v0.8.0)** — every scanned `.txt`/`.md`
109
+ file is also passed through Sieve Referee's quantifier audit lane, which
110
+ flags sentences that make universal claims without backing (`theorem` /
111
+ `enumerated` / `sample`) — the kind of "all X are Y" claim that, with no
112
+ proof or finite enumeration behind it, is a hallucination candidate.
113
+ Flagged sentences surface in their own **Quantifier Audit** tab, one row
114
+ per sentence, with the signal (RED = unbacked universal, YELLOW =
115
+ sample-only or unbacked measured), the matched patterns, and a separate
116
+ **Certainty Markers** section in the detail dialog showing any epistemic
117
+ certainty markers (e.g. 「明白に」「例外なく」) co-occurring in the sentence.
118
+ The lane ships with a bundled default modifier-vocab file; users can
119
+ override the path from Settings to swap in a custom vocabulary.
120
+ - **Local history** — every scan is saved to a local SQLite database
121
+ (`~/.sieve_tray/history.db`); revisit a past run without re-scanning.
122
+ - **Configurable** — default export folder, history retention, UI language,
123
+ and the audit lane's modifier-vocab file (empty = bundled default) are all
124
+ adjustable from a Settings dialog.
125
+ - **File or folder selection (new in v0.9.0)** — point Sieve Tray
126
+ at a whole folder (the original mode) or pick individual files; the
127
+ audit lane runs on a single document, so file-selection mode is a
128
+ natural fit for quick one-off checks.
129
+ - **Self-contained report export (HTML or Markdown)** — every result
130
+ can be exported as a standalone HTML report, or as a Markdown report
131
+ for plain-text / version-controlled workflows.
132
+ - **History clear (new in v0.9.0)** — the History and Sanitize History
133
+ tabs each have a "Clear History" button for when you want to wipe the
134
+ local SQLite store.
135
+ - **Improved signal colors (new in v0.9.0)** — RED and YELLOW rows
136
+ have stronger pastel backgrounds and the signal column is rendered
137
+ in a signal-colored foreground, so flagged rows are easy to spot at a
138
+ glance even on calibrated monitors.
139
+ - **Sanitize text files** — run the bundled Sieve Redact engine over the
140
+ selected folder's `.txt`/`.md` files with a rules file of your choice;
141
+ every output gets a machine-readable receipt, and the summary always
142
+ reports the masked item count and the byte-integrity verification.
143
+ - **Sanitize an image** — drag rectangles on a PNG (8-bit RGB/RGBA) in the
144
+ region editor, preview the real engine output in place, and save a reusable
145
+ region config; every output gets a machine-readable receipt (pixel integrity
146
+ is verified; byte integrity is not applicable to PNG re-encoding).
147
+ - **Sanitize a folder of images** — apply one region config to every PNG
148
+ (8-bit RGB/RGBA) in the folder. The config kind routes the run:
149
+ region-only configs target PNGs, rule/builtin configs target
150
+ `.txt`/`.md`, and files that don't match are reported as excluded
151
+ (never as failures). A config mixing both kinds is rejected up front
152
+ with nothing processed. Every output gets a machine-readable receipt.
153
+ - **Sanitize history tab** — every sanitize run (folder and single
154
+ image) is listed in its own tab with timestamp, folder, config,
155
+ output location, files and ok count, masked items, and integrity
156
+ failures, and refreshes the moment a run completes.
157
+ - **Runs entirely on your machine** — scanning happens 100% locally. Submission
158
+ contents never leave your device: no cloud upload, no API calls involved.
159
+ - **Zero-dependency core** — the scanning engine (`sieve_tray.py`) itself
160
+ uses only the Python standard library plus Sieve Lens / Sieve Scope /
161
+ Sieve Referee. The GUI is an optional layer (`PySide6`) on top, kept
162
+ separate so the core stays consistent with the rest of the Sieve series'
163
+ "zero dependency, offline, deterministic" design.
164
+ - **Cross-platform desktop builds** — CI produces standalone Windows and
165
+ macOS (Apple Silicon + Intel) apps via PyInstaller; no Python installation
166
+ required to run them.
167
+
168
+ ---
169
+
170
+ ## 📦 Installation
171
+
172
+ ### Option 1: Download a pre-built app (recommended)
173
+
174
+ No Python required. Download the build for your platform from the
175
+ [Releases page](https://github.com/neguseatama/sieve-tray/releases):
176
+
177
+ | Platform | Asset |
178
+ |---|---|
179
+ | Windows | `SieveTray-windows.zip` |
180
+ | macOS (Apple Silicon / M-series) | `SieveTray-macos-arm64.zip` |
181
+ | macOS (Intel) | `SieveTray-macos-intel.zip` |
182
+
183
+ Unzip and run `SieveTray.exe` / `SieveTray.app`. On first launch, macOS will
184
+ warn that the developer can't be verified (the app isn't code-signed yet) —
185
+ go to **System Settings → Privacy & Security** and click **Open Anyway**.
186
+ Windows SmartScreen may show a similar warning; choose **More info → Run
187
+ anyway**.
188
+
189
+ ### Option 2: Install from source
190
+
191
+ ```bash
192
+ git clone https://github.com/neguseatama/sieve-tray.git
193
+ cd sieve-tray
194
+ python3 -m venv .venv && source .venv/bin/activate
195
+ pip install -e ".[gui]"
196
+ python3 sieve_tray_gui.py
197
+ ```
198
+
199
+ Requires Python 3.10–3.13 (PySide6 does not yet support 3.14).
200
+
201
+ Core only, no GUI (for CLI usage or scripting):
202
+
203
+ ```bash
204
+ pip install -e .
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 💻 Quick Start
210
+
211
+ ### GUI
212
+
213
+ 1. Launch the app.
214
+ 2. Click **Select Folder...** and pick a directory containing one subfolder
215
+ per submission.
216
+ 3. Click **Run Scan**.
217
+ 4. Browse results in the **Documents**, **Code Pairs**, **Text Similarity**,
218
+ and **Quantifier Audit** tabs — sort by column, filter by filename, and
219
+ double-click any row for the full per-axis breakdown (audit rows show a
220
+ separate **Certainty Markers** section in the detail dialog).
221
+ 5. Export a shareable report with **Export HTML Report**. Past runs are
222
+ always available under the **History** tab.
223
+
224
+ (The interface language defaults to English; switch to Japanese from the
225
+ Settings dialog. Takes effect after restart.)
226
+
227
+ ### CLI
228
+
229
+ ```bash
230
+ python3 sieve_tray.py path/to/submissions -o report.html
231
+ ```
232
+
233
+ Expects a directory of subdirectories, one per submission:
234
+
235
+ ```
236
+ submissions/
237
+ student_a/
238
+ essay.docx
239
+ solution.py
240
+ student_b/
241
+ essay.docx
242
+ solution.py
243
+ ```
244
+
245
+ ### As a library
246
+
247
+ ```python
248
+ from pathlib import Path
249
+ from sieve_tray import run_scan, render
250
+
251
+ result = run_scan(Path("submissions"), progress=print)
252
+ print(result.doc_results) # path / mask / flagged / h_states / evidence
253
+ print(result.code_pairs) # a / b / mask / h_states / scores
254
+ print(result.text_pairs) # a / b / signal / mask / pattern_name / reason / h_states / scores
255
+ print(result.audit_results) # v0.8.0: file / sentence_sha256 / sentence_text /
256
+ # patterns / backing / scope / signal /
257
+ # pattern_name / reason / certainty_markers /
258
+ # modifier_vocab_sha256 / modifier_vocab_count
259
+
260
+ Path("report.html").write_text(render(result))
261
+ ```
262
+
263
+ ---
264
+
265
+ ## 🖼️ Screenshots
266
+
267
+ | English UI | Japanese UI |
268
+ |---|---|
269
+ | ![Main window (English)](docs/screenshots/main-window-en.png) | ![Main window (Japanese)](docs/screenshots/main-window-ja.png) |
270
+
271
+ | Code Pairs | Text Similarity |
272
+ |---|---|
273
+ | ![Code pairs tab](docs/screenshots/code-pairs-ja.png) | ![Text similarity tab](docs/screenshots/text-similarity-ja.png) |
274
+
275
+ ---
276
+
277
+ ## 🔬 Testing
278
+
279
+ ```bash
280
+ pip install -e . pytest
281
+ pytest -v
282
+ ```
283
+
284
+ 89 tests cover the core scan/render pipeline (including regression tests for
285
+ a CSS rendering bug and for Sieve Referee's paraphrase detection), the
286
+ history/settings storage layer (save / load / delete / retention pruning,
287
+ including migration from pre-Referee databases), and the i18n string tables
288
+ (English/Japanese key parity), plus the vendored Sieve Redact
289
+ integration (byte-pin sync and exit-code mapping), and the image
290
+ sanitize path (region helpers, receipt handling, and editor widgets
291
+ under an offscreen Qt platform), and the folder-uniform image
292
+ sanitize flow (config-kind routing, excluded-file reporting, and
293
+ tree-level config errors).
294
+
295
+ CI runs this suite on every push (Python 3.10 and 3.12, on Ubuntu), and
296
+ builds Windows/macOS desktop apps on every version tag.
297
+
298
+ ---
299
+
300
+ ## ⚠️ Known Limitations
301
+
302
+ 1. **Code comparison is Python-only.** `.py` is the only extension routed to
303
+ Sieve Scope; other languages are treated as plain documents (or ignored)
304
+ for now.
305
+ 2. **Text-similarity comparison is plain-text only.** `.txt`/`.md` are
306
+ routed to Sieve Referee; rich formats (`.docx`, `.pdf`) are not
307
+ currently extracted to plain text for this comparison, even though
308
+ Sieve Lens still observes them individually.
309
+ 3. **Sieve Referee's `reason` text is Japanese-only,** regardless of UI
310
+ language, since the engine's similarity thresholds are calibrated for
311
+ Japanese text. The detail dialog surfaces it labeled as such.
312
+ 4. **Desktop builds are not code-signed.** Windows SmartScreen and macOS
313
+ Gatekeeper will warn on first launch; this is expected for an unsigned
314
+ build.
315
+ 5. **This is an observation tool, not a judgment tool** (inherited from
316
+ Sieve Lens, Sieve Scope, and Sieve Referee). A flag means "a human should
317
+ look at this", not "this is confirmed misconduct".
318
+ 6. **Sanitize covers plain text and PNG images only** — the folder Sanitize
319
+ action routes by config kind (region-only configs target PNGs,
320
+ rule/builtin configs target `.txt`/`.md`) in a background thread; the
321
+ image editor handles single PNGs (8-bit RGB/RGBA, non-interlaced). Both
322
+ write a machine-readable receipt next to every output. PDF and JPEG
323
+ masking are not supported by the bundled engine.
324
+ 7. **Quantifier audit is Japanese-calibrated** (new in v0.8.0). The audit
325
+ lane's default universal-scope vocabulary and modifier vocabulary are
326
+ tuned for Japanese text; sentences in other languages may not trigger the
327
+ lane even when they make equivalent universal claims. The lane surfaces
328
+ the vocab sha256 and count in the detail dialog so the calibration is
329
+ visible, and the modifier-vocab file can be overridden from Settings.
330
+ 8. **Quantifier audit surfaces candidates, not verdicts.** A RED signal
331
+ means "this sentence makes a universal claim with no backing recorded in
332
+ the tagfile" — it is a hallucination *candidate*, not a confirmed
333
+ hallucination. The tagfile is the source of truth for backing labels
334
+ (`theorem` / `enumerated` / `sample` / `unbacked`); audit_text() does not
335
+ populate the tagfile automatically. A human must confirm whether a
336
+ flagged sentence is actually unbacked or merely un-tagged.
337
+
338
+ ---
339
+
340
+ ## 📚 Related Projects
341
+
342
+ - [Sieve Lens](https://github.com/neguseatama/sieve-lens) — invisible-content
343
+ observation engine (documents)
344
+ - [Sieve Scope](https://github.com/neguseatama/sieve-scope) — code
345
+ similarity detection engine
346
+ - [Sieve Referee](https://github.com/neguseatama/sieve-referee) — text
347
+ paraphrase / plagiarism detection engine
348
+
349
+ ---
350
+
351
+ ## 🎨 Application Icon
352
+
353
+ ![Application icon](assets/icon.png)
354
+
355
+ Design: [AURA_HYSTERICA](http://www.maroon.dti.ne.jp/clover-hp/)
356
+
357
+ ---
358
+
359
+ ## 📄 License
360
+
361
+ MIT License. See [LICENSE](LICENSE) for details.
362
+
363
+ ---
364
+
365
+ ## 👤 Author
366
+
367
+ * **Kai IWASAKI**