Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a20b99a
fix(metadata): trust validated catalogs over stale summary counts
Oct 16, 2026
4235b08
fix(metadata): safely extend catalogs from verified linked sources
Oct 16, 2026
6aeafb6
fix(metadata): normalize advisory counts before assembly
Oct 16, 2026
e5cd83c
fix(metadata): hydrate linked Metron issue identity evidence
Oct 16, 2026
5357160
fix(import): review manual file metadata before paired writing
Oct 16, 2026
2c0b12d
fix(ui): constrain manual import review modal to viewport
Oct 16, 2026
5dbd166
fix: recover retained direct-download metadata without reacquiring
Oct 16, 2026
77fbe70
fix: reconcile shared XML fields during metadata recovery
Oct 17, 2026
840c6ec
fix: preserve embedded formats during metadata recovery
Oct 17, 2026
9e8516d
fix: resume size-blocked direct downloads from retained files
Oct 17, 2026
5fd0d87
fix: preserve compound creator names in paired metadata review
Oct 17, 2026
29478c4
fix: reconcile sort-title whitespace during metadata publication
Oct 17, 2026
420edeb
fix(downloads): explain unverified pack coverage and preserve target …
Oct 17, 2026
db3b0c8
fix(downloads): select needed pack members and retain recovery files
Oct 17, 2026
ed7e56d
fix(downloads): retire stale background jobs with their lifecycle owners
Oct 17, 2026
36eab7c
fix: synchronize background activity counts and refresh lifecycle
Oct 17, 2026
c62dae2
fix(airdcpp): recover unconfirmed requests and dismiss resolved notif…
Oct 17, 2026
3c4183f
fix(airdcpp): route failed bundle owners to actionable recovery
Oct 18, 2026
bce7025
fix(airdcpp): restore issue state after confirmed queue recovery
Oct 18, 2026
72e0863
fix(ui): use standard buttons for AirDC++ recovery actions
Oct 18, 2026
58d0324
fix: reconcile fulfilled overlapping pack requests safely
Oct 18, 2026
fceead9
fix(metadata): preserve long summaries and reject story-only issues
Oct 18, 2026
16c4ed9
fix(recovery): verify retained metadata files across remounts
Oct 18, 2026
daa9d0f
fix(recovery): provide safe replacement workflow for partial issues
Oct 18, 2026
484906c
fix(story-arcs): validate destinations and retry current file work
Oct 18, 2026
917b74c
fix(story-arcs): refresh review totals with file sync progress
Oct 18, 2026
7427071
fix(ui): keep multiple tabs responsive during searches
Oct 18, 2026
a48c45f
fix(metadata): separate Metron request pacing from account failures
Oct 18, 2026
5dfbeb5
fix(airdcpp): allow reviewed semantic rejection grabs safely
Oct 18, 2026
987270c
fix(resolvers): reserve deadline budget for ranked fallback
Oct 18, 2026
22d2ecf
fix(search): allow bounded Anna browser challenge completion
Oct 18, 2026
d1bf02e
fix(search): explain resolver backoff and source failures safely
Oct 19, 2026
12c4151
fix(ui): show active download sizes and story arc preview loading
Oct 20, 2026
61c5565
feat(metadata): add guarded single-issue metadata editor
Oct 20, 2026
c075947
feat(metadata): add guarded series and sidecar editor
Oct 20, 2026
e115350
feat(metadata): propagate selected series fields to comic files
Oct 20, 2026
ac46ddf
fix(metadata): stabilize propagation approvals across restarts
Oct 20, 2026
4c1824c
fix(metadata): preserve post-import edits during rollback
Oct 21, 2026
c0c93fe
fix(release): qualify metadata recovery and refresh security baseline
Oct 21, 2026
8a1b306
test(import): isolate manual metadata browser settings
Oct 21, 2026
3d3b4b4
fix(security): update stylesheet parser dependencies
Oct 21, 2026
fa335bf
fix(airdcpp): coordinate recovery cancellation with queue admission
Oct 21, 2026
8e8a8c5
test(recovery): wait for filesystem change-time evidence
Oct 21, 2026
ab7f19c
test(conversion): exclude access time from unchanged-file assertions
Oct 21, 2026
83d40a2
test(e2e): use portable per-test screenshot paths
Oct 21, 2026
73ef3db
test(airdcpp): make retry outcome assertions deterministic
Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
686 changes: 38 additions & 648 deletions .grype.yaml

Large diffs are not rendered by default.

37 changes: 36 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
reconciled metadata, verified provider links, and field provenance. Safe custom
JSON fields are preserved; shared, reference-only, and read-only folders stay
unchanged. Split managed folders are reviewed individually.
- Added reviewed single-issue metadata editing and a separate series editor for
saved library metadata and `series.json`. Writes retain verified identities,
field provenance, and coordinated ComicInfo.xml/MetronInfo.xml output.
- Added explicit series-to-comic metadata propagation with selected fields and
files, per-file previews, background progress, cancellation, and resumable writes.
Saving series metadata alone does not modify comic files.
- Added recovery and dismissal actions for interrupted AirDC++ work, a reviewed
Grab anyway action for eligible rejected results, and a replacement workflow
for incomplete story-only downloads.

### Fixed

- Reconciled stale provider catalog counts and safely extended linked issue
catalogs without replacing existing matches or owned files. Repeated Metron
searches now respect provider cooldowns and distinguish timeouts from empty results.
- Recovered retained downloads and overlapping series packs without downloading
or rewriting already imported comics. Oversized files can receive a bounded
approval using the retained download instead of starting again.
- Corrected shared XML metadata reconciliation and restart-sensitive recovery
checks while retaining archive, identity, and changed-file protections.
- Allowed metadata edits and conversion after completed imports. Later import
rollback preserves edited files and dependent library records and reports that
preservation instead of deleting the user's subsequent work.
- Corrected background activity counts and refresh, restored active download
sizes, and prevented multiple issue tabs from exhausting activity connections
or leaving the interface stuck after a stylesheet load failure.
- Added visible Story Arc preview loading and actionable folder validation and
retry for separate reading-order copies, preserving canonical comics.

### Security

- Updated Pillow to the patched 13.0 line for image decoding and conversion.
- Updated the development stylesheet compiler's source-map parser and file
watcher to remove vulnerable parser dependencies.

Automatic import metadata writing, GCD API v2, and LOCG enrichment are not enabled
by this development preview. This is not the completed v2.0 general release.
by default in this development preview. The experimental Anna verification flow
is not included. This is not the completed v2.0 general release.

## [1.3.0] - 2026-09-15

Expand Down
24 changes: 24 additions & 0 deletions docs/development/DATABASE_STANDARDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,15 @@ persist across refreshes until a new archive comparison updates them. The caller
still owns independent file/target matching and atomic application to entity rows;
baseline persistence alone neither establishes that match nor permits file writes.

An explicit metadata-editor override reset may retain `provider_managed=true` on a
field origin. It cannot simultaneously claim an override, source, derivation,
embedded document or passive release. It authorizes normal configured-provider
refresh to replace that unchanged value; subsequent manual edits remain protected.
The current value stays in place until refresh supplies a usable replacement.
Older snapshots without the flag retain their existing behavior. See
[the issue editor contract](ISSUE_METADATA_EDITOR.md) and
[the series editor contract](SERIES_METADATA_EDITOR.md) for field and rollback scope.

### Archive Publication Intent

`archive_metadata_publications` stores versioned, bounded evidence before a paired
Expand Down Expand Up @@ -555,6 +564,21 @@ reassigned registrations. A successor must be finalized for that exact unchanged
action, and its verified fingerprint/digest must still match the actual archive.
The original source remains subject to the existing rollback policy.

Independent metadata edits and conversions may proceed after the import reaches
a terminal state with no outstanding control request. They lock related import
jobs/files before the library binding, recheck admission before publication and
record `post_import_edit` in ImportedFile diagnostics with successful file-state
accounting. Original signatures, placement payloads and import-time successor
receipts remain unchanged. Successful explicit edits supersede pending/failed
import enrichment for that file rather than letting older work overwrite them.
Rollback preserves these files, registrations and dependent series actions,
including folder renames. Its partial result counts intentional preservation
separately from manual recovery. Active publications/conversions also preserve
their parent folder while recovery establishes the outcome. A proven publication
may finish accounting after rollback is requested; it must not rewrite the file.
No-op previews/writes do not create preservation markers or disable ordinary
rollback of untouched imports. No schema migration or history detachment is used.

A stopped owner may receive a `settled` receipt for a proven published successor.
It updates only registered file accounting and the import's successor reference,
marking enrichment cancelled without applying canonical snapshots or baselines.
Expand Down
22 changes: 22 additions & 0 deletions docs/development/DIRECT_PACK_METADATA_WRITING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@ hard-crash or lost-final-commit recovery guarantees beyond the existing executor
Combined books are not split into guessed page boundaries, and mixed-series
packs remain rejected by the existing extractor.

## Overlapping Pack Completion

If another request imports the same issue during pack preparation, the guarded
ownership failure is now `direct_pack_ownership_changed`, not a single-file XML
conflict. Pack completion checks only affected requests; Retry import also uses
this completion path. The exact legacy ownership-guard error is recognized.

Reconciliation verifies a sole owned CBZ, matching embedded issue ID and number,
non-conflicting metadata, archive safety/integrity, and unchanged file/metadata
bindings under the existing mutation lock. Optional descriptive enrichment does
not require rewriting the comic. Missing, ambiguous, unsafe, changed, replacement,
and genuine metadata-conflict cases stay unresolved.

The redundant request is superseded, its Recovery entry is resolved, and its
activity notification no longer requires attention. Original failure evidence
and the retained pack remain available. The failed attempt is not recorded as a
second successful import, and no download or file write is performed.

`tests/integration/metadata_identity/test_direct_pack_completion.py` covers both
completion orderings, legacy recovery, optional enrichment, positive identity
proof, unchanged bytes, cancellation, and concurrent file/metadata changes.

## Qualification

`tests/integration/metadata_identity/test_direct_pack_writer_boundary.py`
Expand Down
69 changes: 69 additions & 0 deletions docs/development/ISSUE_METADATA_EDITOR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Single-Issue Metadata Editor

This is the first manual-editing milestone, not the completed full-field,
series/sidecar or bulk-editing scope. Anna verification is unrelated and parked.

## User Workflow

On an owned issue, choose **Edit metadata**. The default **Differences** view
highlights existing disagreements; **All fields** exposes the catalog inventory
even when no conflict exists. Select the fields, choose saved library/XML values
or enter corrections, then **Update preview** and **Apply selected changes**.
Preview does not query providers or write files. The existing background progress
and cancellation controls apply after approval.

Only selected issue fields acquire correction intent. Clear is explicit and
remains empty during refresh. Remove manual override keeps the current value
now but permits later provider refresh to replace it. Selecting an absent source
cannot erase a nonempty value; the user must choose Clear. Closing before Apply
does not change library metadata or files.

## Current Field Inventory

| Field | Type / validation | ComicInfo | MetronInfo | Behavior |
| --- | --- | --- | --- | --- |
| Issue title | Bounded text | Title | Stories/Story | Editable |
| Summary | Bounded text | Summary | Summary | Editable |
| Cover date | ISO date | Year/Month/Day | CoverDate | Editable, distinct from store date |
| Store date | ISO date | No native equivalent | StoreDate | Editable; does not overwrite the cover date |
| Catalog page count | Integer 0-1000000 | PageCount | PageCount | Editable, never changes physical pages |
| Creator credits | Up to 128 normalized Name / Role entries | Role-specific elements | Credits | Editable; resource IDs/unsupported content block destructive changes |
| Issue number, native provider IDs | Identity | Number/Web | Number/IDs | Protected; use validated provider linking |
| Cover artwork URL | Artwork | Existing renderer projection | Existing renderer projection | Protected; artwork workflow |
| Series title, sort title, publisher, summary, dates, type, archive format, status, count, volume, language, artwork | Series-wide catalog values | Existing series projection | Existing series projection | Read-only; no changes to siblings |
| Rating, genres, tags, characters, teams, locations, imprint, arcs/positions | Preserved XML-only values | Corresponding elements | Corresponding elements | Display both documents; existing Write file metadata resolves disagreements |

Arbitrary extension nodes, resource identifiers and page annotations remain under
the existing preservation contract, not editable raw XML. Full XML-only field
editing, series/series.json editing, member-file propagation and bulk editing
remain outstanding. This milestone does not claim all-schema editing completion.

## Safety Boundary

The editor currently requires one independently bound, managed CBZ/ZIP. Missing,
referenced/read-only, import-owned and ambiguous files retain the existing
writer's rejection. Native formats require the separate explicit conversion
workflow. There is no implicit conversion, rename, move, download or sidecar write.

Preview binds the exact field actions into the existing evidence key. Apply and
the worker revalidate file identity, ownership and current library state. The
existing archive publication journal publishes the reconciled pair and finalizes
canonical values, credits and provenance. Unselected disagreements still block;
select-all does not approve identity changes or shared XML conflicts.

The optional `FieldOrigin.provider_managed` flag records an explicit override
reset without inventing provider attribution. Existing snapshots remain readable.
New snapshots may contain this flag, so rollback to an older application requires
the corresponding consistent database backup, not just an old container image.
Normal refresh behavior is unchanged unless this explicit flag is present.

## Focused Qualification

Tests cover clean/empty/protected fields, selected XML/custom values, clear/reset
across refresh, stale approval, source replacement, cancellation, preserved pages,
unchanged series values, CSRF and request validation. Browser tests cover all
three themes, mobile bounds, accessible controls, unsaved-value retention,
preview/apply and real progress components. Existing paired-writing/recovery
tests remain part of the focused regression set. PostgreSQL uses the same
parametrized integration tests when its test database is configured; a skipped
PostgreSQL case is not qualification evidence.
74 changes: 74 additions & 0 deletions docs/development/SERIES_METADATA_EDITOR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Series Metadata Editor

This milestone edits one series and its eligible `series.json` outputs. Comic-file
propagation and bulk editing remain separate. Anna verification is parked.

## User Workflow

Open **Edit metadata** from series details. **Differences** shows saved-value
disagreements; **All fields** also exposes unchanged, empty and protected fields.
Select fields and choose a saved value, enter a correction, intentionally clear
an optional value, or remove a manual override. Preview before applying.

The default destination is **Library and eligible series.json files**. **Library only** is an
explicit choice, including for reference-only libraries. Preview lists actual
sidecar destinations and blocked locations. No remote provider is queried, and
the editor does not claim to have fetched new source values.

Manual corrections and intentional clears survive provider refresh. Removing an
override keeps the current value until configured refresh supplies a replacement.
Missing source values cannot silently erase data. Required values cannot be
cleared. User choices remain available after validation errors.

## Field Inventory

| Field | Scope and output |
| --- | --- |
| Series title and sorting title | Library and canonical sidecar; never renames folders or comics |
| Publisher and description | Library and canonical sidecar; does not edit issue summaries |
| Start/end year, status and series type | Validated series values and canonical sidecar |
| Archive format | Publication format, distinct from Pullbox's internal series type |
| Volume and language | Canonical baseline and sidecar; no member comic propagation |
| Issue count | Protected catalog value; editing metadata cannot create catalog rows |
| Provider IDs and cover artwork | Protected; use validated provider linking or artwork workflow |
| Aliases and safe custom JSON | Preserved; not a raw JSON editor |

## Safety Boundary

The editor changes no issue records, archive members, reading progress, import
history, ownership, filenames or folder names. It does not convert, download,
delete or move comics. Mixed folders, referenced files, read-only roots and
active import/archive mutations retain their existing write protections.

One reviewed series snapshot supplies the canonical metadata and sidecar output.
Revisions, identity and destination evidence are rechecked before publication.
Each sidecar uses the existing atomic publisher; multiple files and the database
are not one atomic transaction. Results must distinguish a saved library record
from completed, blocked or still-pending sidecar writes. A retry must preserve
completed output and never silently broaden the approved destinations.

The library update and retained sidecar job are committed together. Sidecar work
uses the existing background utility queue. Closing the dialog does not cancel
it; cancelling stops unfinished sidecars, not the already-saved library update.
**Retry unfinished sidecars** rechecks the original destinations without applying
the library correction again. An output published before an interrupted receipt
is recognized by its exact contents and is not rewritten. Changed library values,
folder ownership or unexpected sidecar contents require a new preview.

Safe unknown JSON content is retained. Invalid or identity-conflicting sidecars
are not overwritten. Library-only editing is not permission to repair or replace
those files. ComicInfo.xml and MetronInfo.xml remain unchanged by this editor.
Explicit shared-field propagation is a separate action documented in
[Series Metadata Propagation](SERIES_METADATA_PROPAGATION.md).

Explicitly edited descriptive fields also update their recognized legacy JSON
aliases, including `summary`/`description`. Unselected aliases and unrelated custom
JSON are preserved. The ordinary sidecar exporter keeps its existing behavior.

## Focused Qualification

Qualify selected edits, explicit clears and resets, stale previews, partial
sidecar publication, retry/cancellation, split managed folders, reference/mixed
root exclusions and unchanged comic bytes on SQLite and PostgreSQL. Browser
checks cover modal bounds, standard controls, focus, all themes, progress and
unsaved-value retention. No PR or full CI is part of this private deployment.
Loading
Loading