Write down the trash requirement the code already implements
The traceability gate failed on an orphan tag: seventeen sites across dr-catalog, dr-sync, dr-thumbs and the UI claim FR-CAT-15, and requirements.md defines FR-CAT-1 through FR-CAT-14. Not a typo and not a renumbering — the trash was built, designed and documented in the modules that implement it, and the requirement itself was never written. An orphan is the gate working: a tag naming an undefined ID would otherwise count as covered, which is how a matrix comes to report coverage of things nobody specified. FR-CAT-15 now says what trash.rs does, in the terms the module already argues: a soft delete moves the file into `.darkroom-trash/` and the catalog records that it happened, because a flag alone would not survive invariant 5.2.4 — the catalog is rebuildable from sources, so a rescan would find every deleted file still in the library and re-index it. That is also why the scanner exclusion is part of the requirement rather than an implementation detail; the folder and the exclusion are one mechanism and neither works alone. Permanent delete removes the file before the row, a delete of something already gone counts as success, and the count and bytes are shown before emptying. docs/traceability.md is regenerated: 150 requirements, 71 covered, no orphans. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -159,6 +159,22 @@ Lightroom `.lrcat` and a darktable `library.db`. Edit graphs are explicitly **no
|
|||||||
develop parameters do not translate meaningfully between pipelines, and a partial translation is
|
develop parameters do not translate meaningfully between pipelines, and a partial translation is
|
||||||
worse than none. This is the path in for users with existing libraries.
|
worse than none. This is the path in for users with existing libraries.
|
||||||
|
|
||||||
|
**FR-CAT-15 — Trash and permanent delete.** Deleting an image shall be reversible by default. A
|
||||||
|
soft delete **moves the file** into a `.darkroom-trash/` folder under the library root and records
|
||||||
|
in the catalog when it was trashed and the path it came from; restore moves it back to that path.
|
||||||
|
Permanent delete removes the file first and the catalog row second, and a delete of something
|
||||||
|
already gone counts as success.
|
||||||
|
|
||||||
|
A flag alone would not survive invariant 5.2.4: the catalog is rebuildable from sources, so a
|
||||||
|
rescan would find every "deleted" file still in the library and re-index it. The folder is the
|
||||||
|
durable fact and the row is the convenience — which also means the scanner shall exclude the trash
|
||||||
|
folder, and that a user can recover by hand without DarkRoom. Derived data keyed on the file
|
||||||
|
(thumbnails, cached previews) is dropped when the image is permanently deleted, not when it is
|
||||||
|
trashed.
|
||||||
|
|
||||||
|
The trash shall be listable newest-first, with the count and total bytes it holds shown before any
|
||||||
|
destructive action, since that figure is what tells the user whether they meant it.
|
||||||
|
|
||||||
### 3.2 RAW decoding
|
### 3.2 RAW decoding
|
||||||
|
|
||||||
**FR-RAW-1 — Format support.** Decode mainstream RAW formats. Minimum launch set: Canon (CR2,
|
**FR-RAW-1 — Format support.** Decode mainstream RAW formats. Minimum launch set: Canon (CR2,
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ Denominators are parsed from [`requirements.md`](requirements.md) at run time, n
|
|||||||
|---|---|
|
|---|---|
|
||||||
| Source files scanned | 93 |
|
| Source files scanned | 93 |
|
||||||
| TRACES tags found | 137 |
|
| TRACES tags found | 137 |
|
||||||
| Requirements defined | 149 |
|
| Requirements defined | 150 |
|
||||||
| Requirements covered | 70 |
|
| Requirements covered | 71 |
|
||||||
| **Coverage** | **47.0%** (70/149) |
|
| **Coverage** | **47.3%** (71/150) |
|
||||||
|
|
||||||
### By type
|
### By type
|
||||||
|
|
||||||
| Type | Covered | Defined |
|
| Type | Covered | Defined |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| FR | 54 | 95 |
|
| FR | 55 | 96 |
|
||||||
| NFR | 14 | 48 |
|
| NFR | 14 | 48 |
|
||||||
| R | 2 | 6 |
|
| R | 2 | 6 |
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ Denominators are parsed from [`requirements.md`](requirements.md) at run time, n
|
|||||||
|
|
||||||
A tag naming an ID `requirements.md` does not define — what renumbering produces, and what a typo produces.
|
A tag naming an ID `requirements.md` does not define — what renumbering produces, and what a typo produces.
|
||||||
|
|
||||||
- `FR-CAT-15`
|
_None._
|
||||||
|
|
||||||
## Tagged requirements
|
## Tagged requirements
|
||||||
|
|
||||||
@@ -36,6 +36,7 @@ A tag naming an ID `requirements.md` does not define — what renumbering produc
|
|||||||
| FR-CAT-1 | [`core/dr-catalog/src/scan.rs:1`](../core/dr-catalog/src/scan.rs#L1), [`core/dr-sync/src/scan.rs:93`](../core/dr-sync/src/scan.rs#L93), [`core/dr-types/src/lib.rs:185`](../core/dr-types/src/lib.rs#L185), [`tools/traceability/src/lib.rs:473`](../tools/traceability/src/lib.rs#L473), [`tools/traceability/src/lib.rs:505`](../tools/traceability/src/lib.rs#L505), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1) |
|
| FR-CAT-1 | [`core/dr-catalog/src/scan.rs:1`](../core/dr-catalog/src/scan.rs#L1), [`core/dr-sync/src/scan.rs:93`](../core/dr-sync/src/scan.rs#L93), [`core/dr-types/src/lib.rs:185`](../core/dr-types/src/lib.rs#L185), [`tools/traceability/src/lib.rs:473`](../tools/traceability/src/lib.rs#L473), [`tools/traceability/src/lib.rs:505`](../tools/traceability/src/lib.rs#L505), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1) |
|
||||||
| FR-CAT-11 | [`ui/dr-ui/src/library.rs:150`](../ui/dr-ui/src/library.rs#L150) |
|
| FR-CAT-11 | [`ui/dr-ui/src/library.rs:150`](../ui/dr-ui/src/library.rs#L150) |
|
||||||
| FR-CAT-12 | [`core/dr-pipeline/src/sidecar.rs:108`](../core/dr-pipeline/src/sidecar.rs#L108) |
|
| FR-CAT-12 | [`core/dr-pipeline/src/sidecar.rs:108`](../core/dr-pipeline/src/sidecar.rs#L108) |
|
||||||
|
| FR-CAT-15 | [`core/dr-catalog/src/schema.rs:258`](../core/dr-catalog/src/schema.rs#L258), [`core/dr-catalog/src/trash.rs:1`](../core/dr-catalog/src/trash.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:366`](../core/dr-sync-nextcloud/src/lib.rs#L366), [`core/dr-sync/src/lib.rs:122`](../core/dr-sync/src/lib.rs#L122), [`core/dr-sync/src/scan.rs:426`](../core/dr-sync/src/scan.rs#L426), [`core/dr-sync/src/scan.rs:57`](../core/dr-sync/src/scan.rs#L57), [`core/dr-thumbs/src/lib.rs:341`](../core/dr-thumbs/src/lib.rs#L341), [`ui/dr-ui/src/collections_ui.rs:1191`](../ui/dr-ui/src/collections_ui.rs#L1191), [`ui/dr-ui/src/collections_ui.rs:730`](../ui/dr-ui/src/collections_ui.rs#L730), [`ui/dr-ui/src/library.rs:150`](../ui/dr-ui/src/library.rs#L150), [`ui/dr-ui/src/library.rs:167`](../ui/dr-ui/src/library.rs#L167), [`ui/dr-ui/src/library.rs:2005`](../ui/dr-ui/src/library.rs#L2005), [`ui/dr-ui/src/library.rs:2037`](../ui/dr-ui/src/library.rs#L2037), [`ui/dr-ui/src/library_ui.rs:112`](../ui/dr-ui/src/library_ui.rs#L112), [`ui/dr-ui/src/library_ui.rs:436`](../ui/dr-ui/src/library_ui.rs#L436), [`ui/dr-ui/src/trash.rs:1`](../ui/dr-ui/src/trash.rs#L1), [`ui/dr-ui/ui/collections.slint:458`](../ui/dr-ui/ui/collections.slint#L458) |
|
||||||
| FR-CAT-1a | [`core/dr-types/src/lib.rs:47`](../core/dr-types/src/lib.rs#L47) |
|
| FR-CAT-1a | [`core/dr-types/src/lib.rs:47`](../core/dr-types/src/lib.rs#L47) |
|
||||||
| FR-CAT-2 | [`core/dr-catalog/src/lib.rs:1`](../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/schema.rs:1`](../core/dr-catalog/src/schema.rs#L1), [`tools/traceability/src/lib.rs:473`](../tools/traceability/src/lib.rs#L473) |
|
| FR-CAT-2 | [`core/dr-catalog/src/lib.rs:1`](../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/schema.rs:1`](../core/dr-catalog/src/schema.rs#L1), [`tools/traceability/src/lib.rs:473`](../tools/traceability/src/lib.rs#L473) |
|
||||||
| FR-CAT-3 | [`core/dr-catalog/src/jobs.rs:1`](../core/dr-catalog/src/jobs.rs#L1), [`core/dr-sync/src/scan.rs:69`](../core/dr-sync/src/scan.rs#L69), [`core/dr-thumbs/src/codec.rs:1`](../core/dr-thumbs/src/codec.rs#L1), [`core/dr-thumbs/src/lib.rs:1`](../core/dr-thumbs/src/lib.rs#L1), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1) |
|
| FR-CAT-3 | [`core/dr-catalog/src/jobs.rs:1`](../core/dr-catalog/src/jobs.rs#L1), [`core/dr-sync/src/scan.rs:69`](../core/dr-sync/src/scan.rs#L69), [`core/dr-thumbs/src/codec.rs:1`](../core/dr-thumbs/src/codec.rs#L1), [`core/dr-thumbs/src/lib.rs:1`](../core/dr-thumbs/src/lib.rs#L1), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1) |
|
||||||
@@ -106,7 +107,7 @@ A tag naming an ID `requirements.md` does not define — what renumbering produc
|
|||||||
|
|
||||||
## Not yet tagged
|
## Not yet tagged
|
||||||
|
|
||||||
79 of 149 requirements have no implementation tag. Expected while the codebase is young; each should gain one as it is built.
|
79 of 150 requirements have no implementation tag. Expected while the codebase is young; each should gain one as it is built.
|
||||||
|
|
||||||
<details><summary>Show untagged requirements</summary>
|
<details><summary>Show untagged requirements</summary>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user