# 04 — SCENARIO A: vikunja 2.3.0 -> 2.6.0, cut decided in `starting`
# guest 9202 (demo-hp-scratch), controller 0.260.0, 2026-09-21
#
# VERDICT: the box ended HONEST. The update resumed after the reboot and finished `done`;
# all four version observables agree on 2.6.0; the seeded task read back unchanged; the
# journal is gone; the household sentence is „Naprakesz" / "Up to date".
#
# THE ONE THING THAT DID NOT GO AS THE BRIEF ASSUMED — stated first because it changes
# how capture (1) should be read:
#   The DECISION was taken in `starting` (12:28:26.244 UTC, poll cadence ~21 ms).
#   But `pct stop 9202` took 3 759 ms to return, and the update moved on inside that window.
#   The journal read OFF the stopped guest proves where the box actually died:
#   phase "verifying", not "starting".
#   `starting` on this box lasts about 0.6 s (12:28:26.244 -> vikunja's own 14:28:26.881+02:00
#   migration line). NO instrument available here can land a guest kill inside it: the poll is
#   fast enough (21 ms), the CUT COMMAND is not (3.8 s).
#   This costs nothing for the measurement, because RecoverUpdates handles `starting` and
#   `verifying` in the SAME branch (update.go:909 `case UpdatePhaseStarting, UpdatePhaseVerifying`).
#   Scenario A and Scenario B therefore exercise one recovery arm, not two. Recorded, not hidden.

## (1) TIMESTAMP TABLE
  poll target             : GET /api/stacks/vikunja, HTTPS keep-alive from DooPlex
  measured poll cadence   : ~21 ms  (per-sample HTTP cost 1.1-1.3 ms + 20 ms sleep)
  Update pressed          : 12:28:23.075 UTC  (POST /api/stacks/vikunja/update -> {"accepted":true})
  phase AT THE DECISION   : "starting"  observed 12:28:26.244 UTC
  cut command             : ssh -S <prewarmed master> demo-hp 'pct stop 9202'
  cut command LATENCY     : 3 759 ms  (returned 12:28:30.006 UTC, rc=0, no output)
  phase the box DIED in   : "verifying"  (from update-journal.json read off the stopped guest)
  guest restarted         : pct start 9202 returned after 3.6 s; controller up 12:29:48 UTC
  total app downtime      : ~79 s (vikunja stopped 12:28:26.9 .. restarted 12:29:47.3 UTC)

## (1b) the phase trace, verbatim from the poller
12:28:21.860 updating=False phase='' label='' state=running err=''
12:28:23.088 updating=True phase='safety-dump' label='Adatbázis pillanatkép…' state=running err=''
12:28:23.110 updating=True phase='pinning' label='Új verzió letöltése…' state=running err=''
12:28:23.132 updating=True phase='pulling' label='Új verzió letöltése…' state=running err=''
12:28:26.244 updating=True phase='starting' label='Indítás az új verzióval…' state=running err=''
--- DECISION at 12:28:26.244: phase='starting' -> firing cut: ssh -S /tmp/cm-demohp demo-hp 'pct stop 9202'
--- CUT returned rc=0 after 3759 ms
--- CUT stdout: 
--- CUT stderr: 

=== TIMESTAMP TABLE (vikunja) ===
poll cadence           : measured below
phase at decision      : 'starting' at 12:28:26.244 UTC
cut command            : ssh -S /tmp/cm-demohp demo-hp 'pct stop 9202'
cut command latency    : 3759 ms (returned 12:28:30.006 UTC)

## (1c) update-journal.json read from the STOPPED guest
# The brief's path was WRONG for this guest: /var/lib/lxc/9202/rootfs/var/lib/felhom is an
# EMPTY MOUNTPOINT while the guest is stopped, because mp0 is a separate raw volume
# (nvme-scratch:9202/vm-9202-disk-1.raw). The POSITIVE CONTROL failed there: no catalog-cache/.
/bin/bash: line 131: pct: command not found
#  DOES attach mp0, and then the same path is real (catalog-cache/ present).
/bin/bash: line 132: pct: command not found
/bin/bash: line 132: pct: command not found
# Remember to  afterwards or  refuses.
{
  "updates": {
    "vikunja": {
      "phase": "verifying",
      "started_at": "2026-09-21T12:28:23.06699273Z",
      "prev_pin": {
        "vikunja": "vikunja/vikunja:2.3.0"
      },
      "prev_compose": "/opt/docker/stacks/vikunja/pre-update-compose.yml",
      "prev_applied": "/opt/docker/stacks/vikunja/pre-update-applied.yml",
      "proven_copy_at": "2026-09-21T12:26:12Z",
      "proven_tier": 1
    }
  }
}
## (2) RecoverUpdates log lines after the restart, VERBATIM
2026/09/21 12:29:48 update.go:909: [WARN] [stacks] update recovery: vikunja was interrupted in verifying (started 2026-09-21T12:28:23Z) — the new version may have run; marking it Updating and RESUMING the health wait
2026/09/21 12:29:48 update.go:951: [INFO] [stacks] update vikunja: resuming after a controller restart — `up -d` then the health wait
2026/09/21 12:29:48 update.go:858: [INFO] [stacks] update vikunja: phase verifying
2026/09/21 12:29:48 update.go:652: [INFO] [stacks] update vikunja: healthy after 0s (the app's health check passed)
2026/09/21 12:29:49 update.go:658: [INFO] [stacks] update vikunja: DONE in 1m26s

## (3) THE FOUR VERSION OBSERVABLES, SIDE BY SIDE (after recovery)
1_pinned_images    : {"vikunja": "vikunja/vikunja:2.6.0"}
2_installed_images : {"vikunja": "vikunja/vikunja:2.6.0"} | digest: {"vikunja": "sha256:417ada6f94e81f0267a"}
   (updating=False phase=done label=Frissítve err=- hold=-)
3_live compose line: image: vikunja/vikunja:2.6.0
4_docker inspect   : vikunja/vikunja:2.6.0 | RepoDigest: sha256:417ada6f94e81f0267a | started 2026-09-21T12:29:47.287254768Z
   -> all four name vikunja/vikunja:2.6.0; installed digest and the running container's
      RepoDigest are the same sha256:417ada6f94e81f0267a...

## (4) the seeded data, read back through vikunja's own front door
vikunja version: v2.6.0
TASK 1 'SEED-VIKUNJA-CANARY-9f3c1e-20260921' desc= 'power-cut drill canary'
POSITIVE CONTROL: seed present = True
NEGATIVE CONTROL: absent string present = False

## (4b) the vikunja MIGRATION line, VERBATIM from its container log
3:time=2026-09-21T14:28:26.881+02:00 level=INFO msg="Running migrations…"
5:time=2026-09-21T14:28:26.915+02:00 level=INFO msg="Ran all migrations successfully."
9:time=2026-09-21T14:28:26.922+02:00 level=INFO msg="Vikunja version v2.6.0"
14:time=2026-09-21T14:29:47.713+02:00 level=INFO msg="Running migrations…"
16:time=2026-09-21T14:29:47.734+02:00 level=INFO msg="Ran all migrations successfully."
20:time=2026-09-21T14:29:47.745+02:00 level=INFO msg="Vikunja version v2.6.0"
   -> the FIRST migration ran at 14:28:26.881+02:00 = 12:28:26.881 UTC — 0.64 s AFTER the cut
      decision and 3.1 s BEFORE pct stop returned. The 2.6.0 schema migration had ALREADY
      been applied to the customer's SQLite database when the power went. The pin did not
      roll back (that only happens in the pinning/pulling branch), so old binary vs migrated
      database never happened here — but it is the failure this branch is one step away from.

## (5) the app page's sentence to the household, both languages
vikunja [hu] http=200
   [Naprak] ...tems:center;gap:.5rem"> <span class="stack-state-badge state-run">Fut</span> <span class="tag tag-ok" title="Ez az alkalmazás a legfrissebb elérhető változatot futtatja.">Naprakész</span> <a href="https://tasks.enkisfelhom.hu" target="_blank" class="btn btn-sm btn-outline">Megnyitás ↗</a> <a href="/stacks/vikunja/logs" class="btn btn-sm btn-outl
   NEGATIVE CONTROL 'ZZZNOTPRESENT' found: False
vikunja [en] http=200
   [Up to date] ...align-items:center;gap:.5rem"> <span class="stack-state-badge state-run">Running</span> <span class="tag tag-ok" title="This app is running the newest version available.">Up to date</span> <a href="https://tasks.enkisfelhom.hu" target="_blank" class="btn btn-sm btn-outline">Open ↗</a> <a href="/stacks/vikunja/logs" class="btn btn-sm btn-outline"
   NEGATIVE CONTROL 'ZZZNOTPRESENT' found: False

## (6) done or HELD, and did a journal entry survive?
   ended: update_phase=done, update_phase_label='Frissitve', updating=false, hold_reason=none
   controller log: 'update vikunja: DONE in 1m26s'
   POSITIVE CONTROL: catalog-cache present -> this IS the controller data dir
   ls: cannot access '/var/lib/docker/volumes/felhom-controller-data/_data/data/update-journal.json': No such file or directory
   -> no journal entry survived the reboot.

## STOP CONDITIONS — none tripped
   seeded data gone/unreadable : NO (read back byte-identical)
   updating:true that never clears : NO (cleared 1.3 s after boot)
   journal surviving a 2nd reboot : N/A, no journal survived the 1st
   pin naming one version, container another : NO
   resumed update retrying in a loop : NO (one resume, one success)
   HOLD with no household sentence : N/A, no hold
