Skip to content

app status <slug>: a withdrawn newest row hides an approved+deploying one — "Not live yet" during a live deploy (#390 follow-up) #410

Description

@ZacxDev

Follow-up to #390 / #396. Not a claim that the newest-first pick is wrong — it is deliberate, and #396 pinned it on purpose. The gap is that the rule reproduces the exact symptom #390 set out to eliminate when the newest row is withdrawn.

ownedSubmission (internal/cmd/apps.go:234) takes the first slug-matching row and appViewOwnedAdvice prints its Status / DeployState verbatim. The comment there states the hazard being avoided:

an older row's state reads as plain fact about the newest submission: an author whose newest version is pending over an older approved/live one would be told the wrong deploy state of their own app, with nothing on screen to mark it wrong

A withdrawn newest row produces the same class of wrong answer, in the opposite direction.

What I saw

Immediately after a moderator approved sensei@0.1.1, with the deploy already building:

$ civitai app status sensei
Block ID:         sensei
Version:          0.1.1
Publish request:  pubreq_01KZZ8H20KJ1M753MR4S20SDDV
Status:           withdrawn
Deploy state:     -
Submitted:        2026-08-13 23:29 CDT

Not live yet — sensei.civit.ai only serves after the app is approved and deployed (deployState 'live').

That reads as "your submission was withdrawn and nothing is happening." The truth, from app status --json at the same moment:

id submittedAt status deployState
pubreq_01KZZ8H2… 04:29:48.436Z withdrawn null
pubreq_01KZZ78V… 04:07:50.846Z approved building

It reached live ~2 minutes later. The row the CLI showed was never wrong about itself — it was simply the least informative row available.

Why the withdrawn row was there at all

It was not authored deliberately. Approving one request appears to auto-withdraw the other pending request for the same app: reviewedAt on the approved row is 04:29:49.684Z and updatedAt on the withdrawn row is 04:29:49.689Z5 ms apart. So the platform created the row that then outranked everything by submittedAt.

That is the part worth weighing: the tie-break surfaced a row representing no user intent, and hid the one that did.

Suggested direction

Not "pick the oldest" — that reintroduces #390. Some options, roughly in order of how little they disturb the pinned behaviour:

  1. Keep printing the newest, but never let a terminal-inactive row stand alone. When the newest row is withdrawn/rejected and a non-terminal or approved row exists, print both: newest: 0.1.1 withdrawn · in flight: 0.1.1 approved, building.
  2. Prefer the newest non-withdrawn row for the headline, mentioning the withdrawn one as a footnote.
  3. At minimum, suppress the "Not live yet" line when another row for the same app is approved/live — that sentence is the part that converts a confusing status into a wrong conclusion.

Option 1 keeps #396's invariant intact (the newest row is still what's named) while removing the failure mode, and would also cover the ordinary submit → withdraw → resubmit sequence, not just the auto-withdraw case.

Note on the ordering dependency

apps.go flags that server-side newest-first ordering is "an unverified dependency on the route's contract … every row carries SubmittedAt". In this sample the API did return newest-first, and sorting client-side on SubmittedAt would have produced the same (misleading) pick — so that dependency is not what caused this, and closing it would not fix this.

Observed with a build of main at e49ddc6 (after v0.1.94), i.e. with #396 present.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions