Skip to content

Auto Update on by default outside Docker, honest per-source tagging status, live status rail - #840

Merged
ajslater merged 3 commits into
developfrom
auto-update-default-on
Sep 9, 2026
Merged

ajslater merged 3 commits into
developfrom
auto-update-default-on

Conversation

@ajslater

@ajslater ajslater commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Three unrelated fixes from one session, one commit each.

Auto Update defaults on outside Docker

Installing a new codex over the running one is what a pip, pipx or uv install wants, so the Auto Update flag now seeds on there. A container is an immutable deployment — an in-place upgrade only lives until the next restart brings the image's version back — so Docker keeps seeding it off and updates by image pull.

AdminFlag.FALSE_DEFAULTS splits into the unconditional set (REGISTER_VERIFICATION) and a Docker-only one (AUTO_UPDATE), chosen between by AdminFlag.false_defaults() off is_docker().

Reviewer note: seeding is still get_or_create, so this only affects installs that have no AdminFlag row yet. Existing installs — and any admin who turned the flag off — are untouched. Flipping existing non-docker installs would need a data migration, deliberately not included: it would start those servers upgrading themselves without the admin having asked.

A source that ran and found nothing reads as "No match", not "—"

Comicbox emits a terminal event only for the resolutions its matcher reaches. A search that comes back with zero candidates — routine for Metron, whose database is much smaller than Comic Vine's — ends that source's turn with a log line and no event at all, as does a search that raises and a comic with nothing to search on. The status table had no cell to render and fell back to an em-dash, which reads as "this source was never consulted": the one thing that had not happened.

FileFinished now closes the comic. Every source that announced itself with SourceStarted (emitted after comicbox's first-wins skip, so a source that genuinely sat out never appears) and reported nothing settles as no_match, and an empty cell again means only what it looks like.

Reviewer note: a source whose search raised now reads "No match" too, rather than "—". That is honest about the outcome but does not distinguish an outage from a genuine miss; it is derivable later (SearchStarted with no SearchCompleted) if worth a column state of its own. The cleaner upstream fix is comicbox emitting NoMatch on a zero-candidate search — this close-out stands on its own either way.

The status rail moves in step with the online lookup

The admin drawer's rail renders the LibrarianStatus row, which an online tagging scan only touched when a comic completed — a minute of network per comic during which the rail sat still while the Tagging tab's table, fed by its own snapshot notification, plainly showed work happening.

The live-lookup marker now names the source it is consulting in the status subtitle, so the rail gets the same heartbeat, paced by the live publish's existing one-second floor.

Two supporting fixes in StatusController:

  • update() takes force, for a state change rather than a progress tick. Dropping one of those into the five-second coalescing window loses it instead of deferring it, since it is the whole update. The rate-limit path was already doing this by reaching in and backdating the status's own clock; it asks now.
  • The subtitle is written on every update, including an empty one. It was skipped as "nothing to write", so a phase's subtitle outlived it: a recovered rate limit kept describing the task as rate limited, and the importer's own status.subtitle = "" never took.

Also drops a verbatim duplicate of tagWriteErrorsNotified in the socket store.

Testing

  • pytest: 1107 passed (3 new test modules/classes: admin flag seeding, StatusController coalescing + subtitle writes, the rail half of the live marker)
  • vitest: 491 passed
  • make fix, make lint, make ty: clean

🤖 Generated with Claude Code

ajslater and others added 3 commits September 8, 2026 21:48
Installing a new codex over the running one is what a pip, pipx or uv
install wants, so Auto Update now seeds on there. A container is an
immutable deployment — an in-place upgrade only lives until the next
restart brings the image's version back — so docker keeps seeding it
off and updates by image pull.

Seeding is still get_or_create, so an existing install (and an admin
who turned the flag off) is untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comicbox emits a terminal event only for the resolutions its matcher
reaches. A search that comes back with zero candidates — routine for
Metron, whose database is much smaller than Comic Vine's — ends that
source's turn with a log line and no event at all, as does a search that
raises and a comic with nothing to search on. The status table had no
cell to render and fell back to an em-dash, which reads as "this source
was never consulted": the one thing that had not happened.

FileFinished now closes the comic. Every source that announced itself
with SourceStarted (emitted after comicbox's first-wins skip, so a source
that sat out never appears) and reported nothing settles as no_match, and
an empty cell again means only what it looks like.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The admin drawer's rail renders the LibrarianStatus row, which an online
tagging scan only touched when a comic *completed* — a minute of network
per comic during which the rail sat still while the Tagging tab's table,
fed by its own snapshot notification, plainly showed work happening.

The live-lookup marker now names the source it is consulting in the
status subtitle, so the rail gets the same heartbeat, paced by the live
publish's existing one-second floor.

Two supporting fixes in StatusController:

- update() takes force, for a state change rather than a progress tick.
  Dropping one of those into the five-second coalescing window loses it
  instead of deferring it, since it *is* the whole update. The rate-limit
  path was already doing this by reaching in and backdating the status's
  own clock; it asks now.
- The subtitle is written on every update, including an empty one. It was
  skipped as "nothing to write", so a phase's subtitle outlived it: a
  recovered rate limit kept describing the task as rate limited, and the
  importer's own subtitle clear never took.

Also drops a verbatim duplicate of tagWriteErrorsNotified in the socket
store.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ajslater
ajslater merged commit c5a2254 into develop Sep 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant