lucidplan-82ab300e-a891

job succeeded

starting new job...


→ running command: dir='/etc/byggsteg/job-clone//lucidplan/trunk'
branch='trunk'
if ! command -v git >/dev/null 2>&1; then
  echo 'byggsteg: git is not on this deployment PATH, so the clone cannot be updated' >&2
  exit 1
fi
if ! cd "$dir"; then
  echo "byggsteg: cannot enter the clone $dir" >&2
  exit 1
fi
root=$(git rev-parse --show-toplevel 2>/dev/null)
if [ "$root" != "$(pwd -P)" ]; then
  echo "byggsteg: $dir is not a git checkout; remove it and the next run clones it again" >&2
  exit 1
fi
if ! origin=$(git remote get-url origin 2>/dev/null); then
  echo "byggsteg: $dir has no origin remote to fetch $branch from" >&2
  exit 1
fi
before=$(git rev-parse --short HEAD 2>/dev/null) || before=none
attempt=1
while :; do
  if GIT_TERMINAL_PROMPT=0 git fetch --quiet origin "+refs/heads/$branch:refs/remotes/origin/$branch"; then
    break
  fi
  if [ "$attempt" -ge 3 ]; then
    echo "byggsteg: could not fetch $branch from $origin after 3 attempts; is the branch still there, and is the remote reachable?" >&2
    exit 1
  fi
  echo "byggsteg: fetching $branch from $origin failed; retrying in $((attempt * 2))s" >&2
  sleep $((attempt * 2))
  attempt=$((attempt + 1))
done
if ! git checkout --quiet --force -B "$branch" FETCH_HEAD; then
  echo "byggsteg: fetched $branch from $origin but could not check it out" >&2
  exit 1
fi
after=$(git rev-parse --short HEAD)
if [ "$before" = "$after" ]; then
  echo "byggsteg: $branch was already at $after"
else
  echo "byggsteg: $branch moved from $before to $after"
fi


byggsteg: trunk moved from e7d44ac to 5d0383c

→ running command: cd /etc/byggsteg/job-clone/lucidplan/trunk && uname -a

Linux wolk-jjba 7.2.11-gnu #1 SMP PREEMPT_DYNAMIC 1 x86_64 GNU/Linux

→ running command: cd /etc/byggsteg/job-clone/lucidplan/trunk && git log --name-status HEAD^..HEAD

commit 5d0383cde0503953e08a128895fcda1ea2cf826e
Author: Josep Bigorra <jjbigorra@gmail.com>
Date:   Wed Nov 4 23:22:48 2026 +0100

    feat: Put the project logo in the navigation bar

M       lib/lucidplan/config.scm
M       lib/lucidplan/html.scm
M       maak.scm
M       pub/favicon.ico
D       pub/img/logo-small.jpg
A       pub/img/logo.png
A       pub/img/logo.svg

→ running command: cd /etc/byggsteg/job-clone/lucidplan/trunk && maak test


scanning directories for unit tests...
scanning present working directory for unit tests...

shuffled the files with seed 738092540 (replay with VERITAS_SEED=738092540)

found unit tests: (planning-poker-spec.scm time-entry-spec.scm ticket-triage-spec.scm ticket-estimate-spec.scm ticket-thread-spec.scm burndown-spec.scm)


running unit tests from file: planning-poker-spec.scm, entrypoint: spec


ℹ️ info - shuffled with seed 738092540 (replay with VERITAS_SEED=738092540)
+----------------------------------------------+
[📑 suite] a card of one of the decks
  [🧪 test] the sizes sort by the ladder and not by their letters
    [⚙️ assert] the smallest is the first rung
    ✅ got: 0
    [⚙️ assert] the largest is the last
    ✅ got: 5
    [⚙️ assert] a card nobody deals has no rung
    ✅ got: #f
  [🧪 test] a card is shown with the face the ladder gives it
    [⚙️ assert] a size is shown in capitals
    ✅ got: XXL
    [⚙️ assert] a number is already what it says
    ✅ got: 13
  [🧪 test] the cards are dealt in the ladder's own order
    [⚙️ assert] a hand of points opens on nothing
    ✅ got: (0 1 2 3 5 8 13 21 34)
    [⚙️ assert] a hand of sizes opens on the smallest
    ✅ got: (xs s m l xl xxl)
    [⚙️ assert] a deck nobody deals deals nothing
    ✅ got: ()
  [🧪 test] a card of the room's deck is taken as the deck spells it
    [⚙️ assert] a story point
    ✅ got: 5
    [⚙️ assert] a t-shirt size is lowercased
    ✅ got: m
    [⚙️ assert] space around a card is not part of it
    ✅ got: 8
  [🧪 test] a card nobody deals is refused
    [⚙️ assert] a number off the ladder
    ✅ got: #f
    [⚙️ assert] a size off the ladder
    ✅ got: #f
    [⚙️ assert] a card of the other deck
    ✅ got: #f
    [⚙️ assert] an empty form plays nothing
    ✅ got: #f
    [⚙️ assert] nothing at all plays nothing
    ✅ got: #f
+----------------------------------------------+
[📑 suite] what a table may write onto a ticket
  [🧪 test] a round nobody played has nothing to write down
    [⚙️ assert] no cards, no number
    ✅ got: #f
  [🧪 test] the deck a table deals is the column a ticket carries
    [⚙️ assert] points are the ticket's points
    ✅ got: estimate-points
    [⚙️ assert] sizes are the ticket's size
    ✅ got: estimate-size
    [⚙️ assert] a deck with no column has none
    ✅ got: #f
  [🧪 test] a card the ladder does not hold is not a change
    [⚙️ assert] a number the team does not estimate with
    ✅ got: #f
    [⚙️ assert] a size nobody sizes at
    ✅ got: #f
  [🧪 test] an agreed card is a change a ticket would accept
    [⚙️ assert] the agreed points are a submitable change
    ✅ got: ((estimate-points . 8))
    [⚙️ assert] and the agreed size is one too
    ✅ got: ((estimate-size . xl))
  [🧪 test] a room that agreed on one card has a number to take
    [⚙️ assert] the card everybody played
    ✅ got: 5
    [⚙️ assert] the card most of it played
    ✅ got: 5
    [⚙️ assert] a size is a card too
    ✅ got: m
  [🧪 test] a room that split has nothing to write down
    [⚙️ assert] an even split takes no number
    ✅ got: #f
    [⚙️ assert] and the tally still names both
    ✅ got: (2 5)
+----------------------------------------------+
[📑 suite] the name a participant is known by
  [🧪 test] a name of nothing is no name
    [⚙️ assert] an empty form
    ✅ got: #f
    [⚙️ assert] a form of spaces
    ✅ got: #f
    [⚙️ assert] nothing at all
    ✅ got: #f
    [⚙️ assert] something that is not text
    ✅ got: #f
  [🧪 test] a name is capped because it is a label on a card
    [⚙️ assert] a name at the cap is a name
    ✅ got: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    [⚙️ assert] one character past it is not
    ✅ got: #f
  [🧪 test] a run of spaces inside a name is one space
    [⚙️ assert] the words are kept, the gap is not
    ✅ got: joe the dev
  [🧪 test] the space around a name is not part of it
    [⚙️ assert] a padded name is trimmed
    ✅ got: joe
+----------------------------------------------+
[📑 suite] the deck a table deals
  [🧪 test] a deck is named in the words a reader is shown
    [⚙️ assert] the numbers a team burns down
    ✅ got: story points
    [⚙️ assert] what a first pass is written in
    ✅ got: t-shirt sizes
  [🧪 test] the decks are the two ladders a ticket is estimated on
    [⚙️ assert] the two the section ships
    ✅ got: (points sizes)
    [⚙️ assert] and their sizes are the ticket ladders
    ✅ got: (xs s m l xl xxl)
    [⚙️ assert] and their points are too
    ✅ got: (0 1 2 3 5 8 13 21 34)
  [🧪 test] a deck typed in capitals means the same
    [⚙️ assert] capitals are the same deck
    ✅ got: points
  [🧪 test] a deck the table offers is taken as it is stored
    [⚙️ assert] story points
    ✅ got: points
    [⚙️ assert] t-shirt sizes
    ✅ got: sizes
  [🧪 test] a deck nobody deals is refused
    [⚙️ assert] the fibonacci deck is not one of ours
    ✅ got: #f
    [⚙️ assert] an empty form names no deck
    ✅ got: #f
    [⚙️ assert] something that is not text names no deck
    ✅ got: #f
+----------------------------------------------+
[📑 suite] the ticket a table is about
  [🧪 test] a table opened for a ticket answers which one
    [⚙️ assert] the project and the number in it
    ✅ got: ((project . lucidplan) (number . 479))
  [🧪 test] a table opened for nothing is about no ticket
    [⚙️ assert] a room with no ticket columns at all
    ✅ got: #f
    [⚙️ assert] a project and no number
    ✅ got: #f
    [⚙️ assert] a number and no project
    ✅ got: #f
+----------------------------------------------+
[📑 suite] the seat a browser holds without an account
  [🧪 test] a seat is a room and a secret
    [⚙️ assert] one seat reads back
    ✅ got: ((room-a . secret-1))
    [⚙️ assert] two seats read back in written order
    ✅ got: ((room-a . secret-1) (room-b . secret-2))
  [🧪 test] a value that is not a seat is not a seat
    [⚙️ assert] no cookie at all
    ✅ got: ()
    [⚙️ assert] an empty cookie
    ✅ got: ()
    [⚙️ assert] an entry without a secret
    ✅ got: ()
    [⚙️ assert] an entry with an empty room
    ✅ got: ()
    [⚙️ assert] a malformed entry is skipped, not obeyed
    ✅ got: ((room-b . secret-2))
  [🧪 test] sitting at a second table does not cost the first seat
    [⚙️ assert] the newer seat is written first
    ✅ got: room-b~secret-2|room-a~secret-1
    [⚙️ assert] a seat taken again moves to the front
    ✅ got: room-a~secret-9|room-b~secret-2
  [🧪 test] a seat is found by the room it was taken at
    [⚙️ assert] the seat at one room
    ✅ got: secret-2
    [⚙️ assert] no seat at a room nobody sat at
    ✅ got: #f
  [🧪 test] the number of seats a cookie holds is capped
    [⚙️ assert] the cap is what the section says
    ✅ got: 8
    [⚙️ assert] the newest seat is the one that is there
    ✅ got: secret-new
+----------------------------------------------+
[📑 suite] what a browser may know about a card before the reveal
  [🧪 test] a card is answered once the room is revealed
    [⚙️ assert] a point, revealed
    ✅ got: 5
    [⚙️ assert] a size, revealed, in capitals
    ✅ got: M
  [🧪 test] a seat that played nothing has nothing to show either way
    [⚙️ assert] no card, revealed
    ✅ got: #f
    [⚙️ assert] no card, unrevealed
    ✅ got: #f
  [🧪 test] a card is not answered while the cards are face down
    [⚙️ assert] a point, not yet revealed
    ✅ got: #f
    [⚙️ assert] a size, not yet revealed
    ✅ got: #f
+----------------------------------------------+
[📑 suite] what a round of cards adds up to
  [🧪 test] a tally of sizes is counted too
    [⚙️ assert] two sizes, in ladder order
    ✅ got: ((s . 1) (l . 1))
  [🧪 test] the room agrees on the card most of it played
    [⚙️ assert] the card played most often
    ✅ got: (5)
  [🧪 test] a round nobody played agrees on nothing
    [⚙️ assert] no cards, no agreement
    ✅ got: ()
  [🧪 test] a round nobody played has no tally
    [⚙️ assert] no cards, no rows
    ✅ got: ()
  [🧪 test] a spread is the two ends of the disagreement
    [⚙️ assert] the lowest and the highest of the points
    ✅ got: ((low . 2) (high . 13))
    [⚙️ assert] the ends of the sizes are sizes
    ✅ got: ((low . s) (high . xxl))
  [🧪 test] a card nobody played is not a row of the tally
    [⚙️ assert] two cards were played, in ladder order
    ✅ got: ((2 . 1) (5 . 2))
  [🧪 test] an even split is a split, not a decision
    [⚙️ assert] both cards of a tie, in ladder order
    ✅ got: (2 5)
  [🧪 test] a round with no mean has none
    [⚙️ assert] sizes have no mean
    ✅ got: #f
    [⚙️ assert] no cards have no mean
    ✅ got: #f
  [🧪 test] a room that agrees has no spread
    [⚙️ assert] one card is no spread
    ✅ got: #f
    [⚙️ assert] the same card twice is no spread
    ✅ got: #f
    [⚙️ assert] no cards is no spread
    ✅ got: #f
  [🧪 test] the mean of a round of points is a number
    [⚙️ assert] two cards average where they sit
    ✅ got: 6.5
    [⚙️ assert] one card is its own mean
    ✅ got: 3.0
ℹ️ info - ran 8 tasks in: 0 seconds, 172202 microseconds

running unit tests from file: time-entry-spec.scm, entrypoint: spec


ℹ️ info - shuffled with seed 738092540 (replay with VERITAS_SEED=738092540)
+----------------------------------------------+
[📑 suite] what is not a duration
  [🧪 test] a day's worth is the ceiling
    [⚙️ assert] more than a day is a typo
    ✅ got: #f
    [⚙️ assert] a bare number past the ceiling is a typo
    ✅ got: #f
  [🧪 test] what names no duration at all is refused
    [⚙️ assert] words are refused
    ✅ got: #f
    [⚙️ assert] a negative duration is refused
    ✅ got: #f
    [⚙️ assert] a unit nobody knows is refused
    ✅ got: #f
    [⚙️ assert] a stray character is not skipped
    ✅ got: #f
    [⚙️ assert] something that is not text is refused
    ✅ got: #f
  [🧪 test] no time logged is no entry
    [⚙️ assert] an empty form is refused
    ✅ got: #f
    [⚙️ assert] a form of nothing but space is refused
    ✅ got: #f
    [⚙️ assert] no value at all is refused
    ✅ got: #f
    [⚙️ assert] zero minutes is not time spent
    ✅ got: #f
    [⚙️ assert] zero hours is not time spent either
    ✅ got: #f
  [🧪 test] a clock reading is read as a clock, not as two numbers
    [⚙️ assert] minutes past the hour are minutes
    ✅ got: #f
    [⚙️ assert] a single minute digit is not a clock
    ✅ got: #f
+----------------------------------------------+
[📑 suite] what a ticket's time entries add up to
  [🧪 test] a row that is not a duration does not break the sum
    [⚙️ assert] a malformed row counts as nothing
    ✅ got: 120
  [🧪 test] a ticket nobody logged time on adds up to nothing
    [⚙️ assert] no entries is no minutes
    ✅ got: 0
  [🧪 test] a total reads as a duration and as hours
    [⚙️ assert] one hundred and sixty-five minutes
    ✅ got: 2h 45m
    [⚙️ assert] and as the hours a report adds up in
    ✅ got: 2.75
  [🧪 test] every entry counts toward the total
    [⚙️ assert] two and a half hours over three days
    ✅ got: 165
+----------------------------------------------+
[📑 suite] a number of minutes, said to a reader
  [🧪 test] a whole number of hours is said in hours
    [⚙️ assert] two hours
    ✅ got: 2h
  [🧪 test] less than an hour is said in minutes
    [⚙️ assert] three quarters of an hour
    ✅ got: 45m
  [🧪 test] nothing is said as nothing rather than as empty space
    [⚙️ assert] zero minutes still reads as a duration
    ✅ got: 0m
  [🧪 test] hours and minutes are said together
    [⚙️ assert] an hour and a half
    ✅ got: 1h 30m
  [🧪 test] a number that is not a duration is said as nothing
    [⚙️ assert] no value answers the empty text
    ✅ got: 
    [⚙️ assert] a negative duration answers it too
    ✅ got: 
+----------------------------------------------+
[📑 suite] a number of minutes, added up in hours
  [🧪 test] part of an hour is a fraction of it
    [⚙️ assert] an hour and a half is 1.5
    ✅ got: 1.5
    [⚙️ assert] three quarters is 0.75
    ✅ got: 0.75
  [🧪 test] a whole number of hours is a whole decimal
    [⚙️ assert] an hour is 1
    ✅ got: 1
    [⚙️ assert] two hours is 2
    ✅ got: 2
  [🧪 test] a number that is not a duration is zero hours
    [⚙️ assert] no value answers zero
    ✅ got: 0
+----------------------------------------------+
[📑 suite] a duration, read the ways it is written
  [🧪 test] space around the whole thing is not part of it
    [⚙️ assert] a padded form still means its duration
    ✅ got: 30
  [🧪 test] a duration is read in the words it is spoken in
    [⚙️ assert] two hours, spelled out
    ✅ got: 120
    [⚙️ assert] three quarters of an hour
    ✅ got: 45
    [⚙️ assert] an abbreviation of an hour
    ✅ got: 60
    [⚙️ assert] an abbreviation of minutes
    ✅ got: 15
    [⚙️ assert] a whole day of work is a day
    ✅ got: 1440
  [🧪 test] the case of what was typed does not matter
    [⚙️ assert] capitals are the same duration
    ✅ got: 90
  [🧪 test] an hour and a half is ninety minutes however it is typed
    [⚙️ assert] in hours, with a fraction
    ✅ got: 90
    [⚙️ assert] in minutes alone
    ✅ got: 90
    [⚙️ assert] as hours and minutes, run together
    ✅ got: 90
    [⚙️ assert] as hours and minutes, with a space
    ✅ got: 90
    [⚙️ assert] as a clock reading
    ✅ got: 90
    [⚙️ assert] as a bare number of minutes
    ✅ got: 90
ℹ️ info - ran 5 tasks in: 0 seconds, 90500 microseconds

running unit tests from file: ticket-triage-spec.scm, entrypoint: spec


ℹ️ info - shuffled with seed 738092540 (replay with VERITAS_SEED=738092540)
+----------------------------------------------+
[📑 suite] a status that is not on the list
  [🧪 test] is still a ticket somebody is working on
    [⚙️ assert] an unknown status is bucketed as open
    ✅ got: open
  [🧪 test] reads as itself when there is no label for it
    [⚙️ assert] the value stands in for the label
    ✅ got: polishing
    [⚙️ assert] there is no spec for it
    ✅ got: #f
  [🧪 test] is not in any bucket's list
    [⚙️ assert] the done bucket holds the statuses that are done
    ✅ got: (done)
+----------------------------------------------+
[📑 suite] the order a list is asked for in
  [🧪 test] a keyword the pages offer becomes an ORDER BY
    [⚙️ assert] the title, A to Z
    ✅ got: ((title asc))
    [⚙️ assert] the priority, highest first
    ✅ got: ((priority desc))
  [🧪 test] a keyword nobody offers falls back to the last edited first
    [⚙️ assert] an unknown order is the default one
    ✅ got: ((updated-at desc))
    [⚙️ assert] and so is no order at all
    ✅ got: ((updated-at desc))
+----------------------------------------------+
[📑 suite] an inline change from the ticket's own page
  [🧪 test] a status the project moves through is accepted
    [⚙️ assert] the change is the column and its new value
    ✅ got: ((ticket-status . done))
  [🧪 test] a type is checked against the types a ticket has
    [⚙️ assert] a type on the ladder is accepted
    ✅ got: ((ticket-type . bug))
    [⚙️ assert] a type nothing offers is refused
    ✅ got: #f
    [⚙️ assert] the types are the ones the schema holds
    ✅ got: (task bug story spike time-box)
  [🧪 test] a status the project does not move through is refused
    [⚙️ assert] a status invented by hand changes nothing
    ✅ got: #f
  [🧪 test] with no project list the instance's own is the ladder
    [⚙️ assert] the first status of the instance's list is accepted
    ✅ got: #t
  [🧪 test] a field a ticket has no ladder for is refused
    [⚙️ assert] the priority is not changed this way
    ✅ got: #f
+----------------------------------------------+
[📑 suite] the list a project's tickets move through
  [🧪 test] a project that could not be read is not an error
    [⚙️ assert] no project at all falls back to the instance
    ✅ got: ((todo To-do anchor ⚓ open) (work-in-progress Work in Progress gear-fine ⚙️ open) (in-review In Review list-magnifying-glass 🔍 open) (done Done check ✅ done) (rejected Rejected x ❌ rejected))
  [🧪 test] a project with a list of its own uses it
    [⚙️ assert] the project's own list is the one read
    ✅ got: (todo shipped)
  [🧪 test] a project with none uses the instance's
    [⚙️ assert] a project that says nothing falls back to the instance
    ✅ got: ((todo To-do anchor ⚓ open) (work-in-progress Work in Progress gear-fine ⚙️ open) (in-review In Review list-magnifying-glass 🔍 open) (done Done check ✅ done) (rejected Rejected x ❌ rejected))
+----------------------------------------------+
[📑 suite] the assignee a form submitted
  [🧪 test] an id that was offered is answered
    [⚙️ assert] a known id is taken as it was submitted
    ✅ got: user-1
  [🧪 test] an id that was not offered is refused
    [⚙️ assert] an id no menu offered is not an assignee
    ✅ got: #f
    [⚙️ assert] a value that is not text is not an assignee
    ✅ got: #f
  [🧪 test] no assignee is the absence of one, not an unknown user
    [⚙️ assert] an empty submission leaves the ticket as it was
    ✅ got: #f
+----------------------------------------------+
[📑 suite] statuses written by hand
  [🧪 test] a note and a blank line are skipped rather than read as statuses
    [⚙️ assert] the comment is not a status
    ✅ got: #f
    [⚙️ assert] no status was invented by the blank line
    ✅ got: 3
  [🧪 test] the bucket is read
    [⚙️ assert] a status in the done bucket says so
    ✅ got: done
    [⚙️ assert] a status in the rejected bucket says so
    ✅ got: rejected
  [🧪 test] text that names nothing is not a list of statuses
    [⚙️ assert] an empty block answers #f
    ✅ got: #f
    [⚙️ assert] a block of notes alone answers #f
    ✅ got: #f
  [🧪 test] each field of an entry is read
    [⚙️ assert] the label is read
    ✅ got: To-do
    [⚙️ assert] the icon is read
    ✅ got: anchor
    [⚙️ assert] the glyph is read
    ✅ got: ⚓
  [🧪 test] the values are read in the order they were written
    [⚙️ assert] the read-back values keep their order
    ✅ got: (todo done rejected)
  [🧪 test] a field left out takes the default the rest of the code reads
    [⚙️ assert] a bucket nothing knows is read as open
    ✅ got: open
ℹ️ info - ran 6 tasks in: 0 seconds, 83526 microseconds

running unit tests from file: ticket-estimate-spec.scm, entrypoint: spec


ℹ️ info - shuffled with seed 738092540 (replay with VERITAS_SEED=738092540)
+----------------------------------------------+
[📑 suite] an estimate changed from the ticket's own page
  [🧪 test] a story point nobody offered is refused
    [⚙️ assert] a value off the ladder changes nothing
    ✅ got: #f
    [⚙️ assert] words change nothing
    ✅ got: #f
  [🧪 test] clearing an estimate is a change the menu offers
    [⚙️ assert] the empty row changes the ticket
    ✅ got: ((estimate-points . ))
  [🧪 test] a size the menu offered is accepted
    [⚙️ assert] the change is the column and its value
    ✅ got: ((estimate-size . m))
    [⚙️ assert] clearing a size is offered too
    ✅ got: ((estimate-size . ))
  [🧪 test] a size nobody offered is refused
    [⚙️ assert] a size off the ladder changes nothing
    ✅ got: #f
  [🧪 test] a story point the menu offered is accepted
    [⚙️ assert] the change is the column and its value
    ✅ got: ((estimate-points . 8))
+----------------------------------------------+
[📑 suite] the changes a write to a ticket is recorded with
  [🧪 test] a field that moved is recorded with its two values
    [⚙️ assert] the title, the label and both values
    ✅ got: ((title title a ticket another ticket))
  [🧪 test] the two ways of saying nothing are the same state
    [⚙️ assert] a missing value and an empty text agree
    ✅ got: 
    [⚙️ assert] and both are recorded as the empty text
    ✅ got: 
    [⚙️ assert] a number is recorded as its text
    ✅ got: 21
  [🧪 test] every tracked field has the name a reader knows it by
    [⚙️ assert] the seven tracked fields are named
    ✅ got: ((title title) (description description) (ticket-status status) (ticket-type type) (priority priority) (estimate-points story points) (estimate-size size))
  [🧪 test] an estimate that was never made is not a change
    [⚙️ assert] no estimate answers no change
    ✅ got: ()
  [🧪 test] a ticket submitted back unchanged is not an edit
    [⚙️ assert] nothing moved, so nothing is recorded
    ✅ got: ()
  [🧪 test] an estimate that was cleared is a change
    [⚙️ assert] the estimate it had is recorded
    ✅ got: (3 )
  [🧪 test] a column the tracker does not watch is not a change
    [⚙️ assert] the stamp is not a tracked field
    ✅ got: #f
  [🧪 test] several fields that moved are recorded one row each
    [⚙️ assert] both estimates moved
    ✅ got: 2
+----------------------------------------------+
[📑 suite] a ticket's t-shirt size
  [🧪 test] no size is no estimate
    [⚙️ assert] an empty form is no size
    ✅ got: #f
    [⚙️ assert] a value that is not text is no size
    ✅ got: #f
  [🧪 test] a size on the ladder is taken as it is stored
    [⚙️ assert] a size the menu offered is accepted
    ✅ got: l
    [⚙️ assert] a size typed in capitals means the same
    ✅ got: xl
    [⚙️ assert] space around it is not part of it
    ✅ got: m
  [🧪 test] each size is shown to a reader in capitals
    [⚙️ assert] the smallest is shown in capitals
    ✅ got: XS
    [⚙️ assert] the middle of the ladder
    ✅ got: M
    [⚙️ assert] the largest is shown in capitals
    ✅ got: XXL
    [⚙️ assert] a size nobody knows is shown as itself
    ✅ got: huge
  [🧪 test] a size nobody offers is refused
    [⚙️ assert] a size off the ladder is refused
    ✅ got: #f
    [⚙️ assert] the ladder is the shipped sequence
    ✅ got: (xs s m l xl xxl)
+----------------------------------------------+
[📑 suite] a ticket's story-point estimate
  [🧪 test] the ladder is the one the menus and the endpoints share
    [⚙️ assert] the points are the shipped sequence
    ✅ got: (0 1 2 3 5 8 13 21 34)
  [🧪 test] a number the team does not estimate with is refused
    [⚙️ assert] a value off the ladder is refused
    ✅ got: #f
    [⚙️ assert] a negative estimate is refused
    ✅ got: #f
    [⚙️ assert] words are refused
    ✅ got: #f
    [⚙️ assert] something that is not text is refused
    ✅ got: #f
  [🧪 test] an estimate nobody made is no estimate, not zero
    [⚙️ assert] an empty form is no estimate
    ✅ got: #f
    [⚙️ assert] a blank form is no estimate
    ✅ got: #f
    [⚙️ assert] no value at all is no estimate
    ✅ got: #f
  [🧪 test] a number on the team's ladder is taken as that number
    [⚙️ assert] a value the menu offered is accepted
    ✅ got: 5
    [⚙️ assert] a number arrives as a number as well
    ✅ got: 13
    [⚙️ assert] space around it is not part of it
    ✅ got: 3
    [⚙️ assert] zero is an estimate somebody made
    ✅ got: 0
ℹ️ info - ran 4 tasks in: 0 seconds, 99716 microseconds

running unit tests from file: ticket-thread-spec.scm, entrypoint: spec


ℹ️ info - shuffled with seed 738092540 (replay with VERITAS_SEED=738092540)
+----------------------------------------------+
[📑 suite] the name a file is served under
  [🧪 test] a name that is just a name is kept
    [⚙️ assert] a plain name survives
    ✅ got: report.pdf
  [🧪 test] an empty name is still a name
    [⚙️ assert] nothing submitted answers the generic
    ✅ got: attachment
    [⚙️ assert] a name of nothing but space answers it too
    ✅ got: attachment
    [⚙️ assert] no name at all answers it too
    ✅ got: attachment
  [🧪 test] a name is cut to a length a header can carry
    [⚙️ assert] a very long name is shortened
    ✅ got: #t
  [🧪 test] what a header cannot carry is replaced
    [⚙️ assert] quotes and backslashes do not survive
    ✅ got: my _report_.pdf
    [⚙️ assert] a line break is replaced
    ✅ got: line_break.txt
  [🧪 test] only the last component of a submitted path is kept
    [⚙️ assert] a path is cut to its last component
    ✅ got: passwd
    [⚙️ assert] a separator a path could be written with does not survive
    ✅ got: #f
+----------------------------------------------+
[📑 suite] how big a file is, said in one line
  [🧪 test] bytes are said as bytes
    [⚙️ assert] a small file is counted in bytes
    ✅ got: 512 B
    [⚙️ assert] an empty file is counted too
    ✅ got: 0 B
  [🧪 test] a size nobody knows is not a size
    [⚙️ assert] no size answers nothing
    ✅ got: 
  [🧪 test] larger files are said in the unit a reader expects
    [⚙️ assert] a couple of kilobytes
    ✅ got: 2.0 KB
    [⚙️ assert] a couple of megabytes
    ✅ got: 2.0 MB
+----------------------------------------------+
[📑 suite] the type a file is served as
  [🧪 test] anything a header cannot carry becomes the generic type
    [⚙️ assert] a line break would split the header
    ✅ got: application/octet-stream
    [⚙️ assert] a quoted type is not a type
    ✅ got: application/octet-stream
    [⚙️ assert] no type at all is the generic one
    ✅ got: application/octet-stream
    [⚙️ assert] an empty type is the generic one
    ✅ got: application/octet-stream
  [🧪 test] a media type is kept
    [⚙️ assert] a type a header can carry survives
    ✅ got: text/plain
    [⚙️ assert] a type the application made up survives
    ✅ got: application/vnd.oasis.opendocument.text
+----------------------------------------------+
[📑 suite] how a download is named
  [🧪 test] both the plain and the encoded name are carried
    [⚙️ assert] the disposition carries the two names
    ✅ got: (attachment (filename . my report.pdf) (filename* . UTF-8''my%20report.pdf))
  [🧪 test] a path in the submitted name never reaches the header
    [⚙️ assert] the plain form is cut to the last name
    ✅ got: hosts
  [🧪 test] the disposition is a type and its parameters
    [⚙️ assert] the type is the attachment disposition
    ✅ got: attachment
+----------------------------------------------+
[📑 suite] the thread a ticket's comments make
  [🧪 test] the depth a comment is indented by is how far down it is
    [⚙️ assert] a comment on the ticket is not indented
    ✅ got: 0
    [⚙️ assert] a reply is indented once
    ✅ got: 1
    [⚙️ assert] a reply to a reply is indented twice
    ✅ got: 2
  [🧪 test] a comment nothing answers has no children
    [⚙️ assert] the last word is the last word
    ✅ got: ()
  [🧪 test] an id read back from the database names the same comment
    [⚙️ assert] a numeric parent names the same comment
    ✅ got: 1
  [🧪 test] the comments on the ticket itself are the ones it hangs from
    [⚙️ assert] the roots are the comments with no parent
    ✅ got: (c1 c4)
  [🧪 test] a reply is drawn under what it answers
    [⚙️ assert] the answer to the first word
    ✅ got: (c2)
    [⚙️ assert] nothing answers the answer but one
    ✅ got: (c3)
  [🧪 test] a thread that was written wrong still terminates
    [⚙️ assert] a cycle is answered at the depth reached
    ✅ got: 2
    [⚙️ assert] a missing parent is answered at the root
    ✅ got: 0
ℹ️ info - ran 5 tasks in: 0 seconds, 94865 microseconds

running unit tests from file: burndown-spec.scm, entrypoint: spec


ℹ️ info - shuffled with seed 738092540 (replay with VERITAS_SEED=738092540)
+----------------------------------------------+
[📑 suite] counting the days between two of them
  [🧪 test] a day and its number are each other's
    [⚙️ assert] the number of a day names it back
    ✅ got: 2026-10-27
  [🧪 test] the answer is negative when the second day is earlier
    [⚙️ assert] a week the other way
    ✅ got: -7
  [🧪 test] a value that is not a day is no difference
    [⚙️ assert] two things that are not days
    ✅ got: #f
  [🧪 test] the same day is no days apart
    [⚙️ assert] a day and itself
    ✅ got: 0
  [🧪 test] month lengths and leap years do not disturb the count
    [⚙️ assert] across the end of a short month
    ✅ got: 7
    [⚙️ assert] across a leap day
    ✅ got: 2
    [⚙️ assert] across a new year
    ✅ got: 2
  [🧪 test] a week is seven days
    [⚙️ assert] seven days
    ✅ got: 7
+----------------------------------------------+
[📑 suite] the line a sprint is burnt down along
  [🧪 test] a sprint with nothing in it is a flat line at nothing
    [⚙️ assert] every day is zero
    ✅ got: (0 0 0)
  [🧪 test] a ticket that was reopened is not still counted as done
    [⚙️ assert] five points are burnt on the second day
    ✅ got: 8
    [⚙️ assert] and they come back when the ticket does
    ✅ got: 13
  [🧪 test] the summary is the last day said once
    [⚙️ assert] thirteen committed
    ✅ got: 13
    [⚙️ assert] five done
    ✅ got: 5
    [⚙️ assert] eight left
    ✅ got: 8
  [🧪 test] the committed line falls evenly to nothing on the last day
    [⚙️ assert] the first day is the whole commitment
    ✅ got: 13.0
    [⚙️ assert] the second day is three quarters of it
    ✅ got: 9.75
    [⚙️ assert] the third day is half of it
    ✅ got: 6.5
  [🧪 test] work finished on a day is burnt on that day, not before
    [⚙️ assert] nothing is done on the first day
    ✅ got: 13
    [⚙️ assert] five points are gone on the second
    ✅ got: 8
    [⚙️ assert] and they stay gone on the third
    ✅ got: 8
  [🧪 test] a closed sprint is drawn to its last day
    [⚙️ assert] all five days, read afterwards
    ✅ got: 5
  [🧪 test] the point a day started with is the scope and what was done
    [⚙️ assert] thirteen points were committed
    ✅ got: 13
    [⚙️ assert] five of them were done
    ✅ got: 5
  [🧪 test] an unestimated ticket adds nothing to the sum
    [⚙️ assert] the unsized ticket is not counted
    ✅ got: 5
  [🧪 test] a day is drawn up to today and no further
    [⚙️ assert] three days of a five-day sprint
    ✅ got: (2026-10-01 2026-10-02 2026-10-03)
  [🧪 test] a sprint whose end is before its beginning is not drawn
    [⚙️ assert] a backwards sprint draws nothing
    ✅ got: ()
  [🧪 test] a ticket taken out of the sprint stops counting
    [⚙️ assert] the scope still holds it on the first day
    ✅ got: 13
    [⚙️ assert] it is gone from the second day on
    ✅ got: 5
    [⚙️ assert] and nothing but the done ticket is left
    ✅ got: 0
  [🧪 test] a sprint with no dates is not drawn
    [⚙️ assert] no days to draw
    ✅ got: ()
+----------------------------------------------+
[📑 suite] how a deadline stands, read against today
  [🧪 test] the warning is a week, and it is the same week everywhere
    [⚙️ assert] the threshold the pages share
    ✅ got: 7
  [🧪 test] a day within the warning is due soon
    [⚙️ assert] a week out is close enough to worry about
    ✅ got: due-soon
    [⚙️ assert] tomorrow is close enough too
    ✅ got: due-soon
  [🧪 test] today is today
    [⚙️ assert] the day itself
    ✅ got: due-today
  [🧪 test] a ticket with no deadline has no state
    [⚙️ assert] no deadline answers nothing
    ✅ got: #f
    [⚙️ assert] a deadline that is not a day answers nothing
    ✅ got: #f
  [🧪 test] a day further out is simply scheduled
    [⚙️ assert] the day after the warning
    ✅ got: scheduled
  [🧪 test] a day that has passed is overdue
    [⚙️ assert] yesterday is overdue
    ✅ got: overdue
+----------------------------------------------+
[📑 suite] the states a sprint can be in
  [🧪 test] the three states are the shipped ladder
    [⚙️ assert] planned, active, closed
    ✅ got: (planned active closed)
  [🧪 test] a state on the ladder is taken as it is stored
    [⚙️ assert] an ordinary state
    ✅ got: active
    [⚙️ assert] a state typed in capitals means the same
    ✅ got: closed
  [🧪 test] a stretch of days has to run forwards
    [⚙️ assert] an end before its beginning is refused
    ✅ got: #f
    [⚙️ assert] an undated sprint is allowed
    ✅ got: #t
    [⚙️ assert] an open-ended sprint is allowed
    ✅ got: #t
  [🧪 test] a state nobody offers is refused
    [⚙️ assert] a state off the ladder is refused
    ✅ got: #f
    [⚙️ assert] something that is not text is refused
    ✅ got: #f
  [🧪 test] only one state is the one a team is in
    [⚙️ assert] active is running
    ✅ got: #t
    [⚙️ assert] planned is not
    ✅ got: #f
+----------------------------------------------+
[📑 suite] the day a submitted date names
  [🧪 test] a day written the way a date field writes it is read
    [⚙️ assert] an ordinary day
    ✅ got: 2026-10-27
    [⚙️ assert] space around it is not part of it
    ✅ got: 2026-10-27
  [🧪 test] what is not a date is refused
    [⚙️ assert] an empty form is no date
    ✅ got: #f
    [⚙️ assert] no value at all is no date
    ✅ got: #f
    [⚙️ assert] a date without its day is refused
    ✅ got: #f
    [⚙️ assert] a date written the other way round is refused
    ✅ got: #f
    [⚙️ assert] a month that does not exist is refused
    ✅ got: #f
  [🧪 test] a day that does not exist is refused
    [⚙️ assert] the 31st of February is not a day
    ✅ got: #f
    [⚙️ assert] the 31st of April is not a day
    ✅ got: #f
    [⚙️ assert] the 29th of February 2026 is not a day
    ✅ got: #f
    [⚙️ assert] the 29th of February 2028 is a leap day
    ✅ got: 2028-02-29
ℹ️ info - ran 5 tasks in: 0 seconds, 199645 microseconds

finished running tests
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling test/veritas/unit/planning-poker-spec.scm
;;; compiling lib/lucidplan/domain.scm
;;; compiling lib/lucidplan/config.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/lib/lucidplan/config.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/lib/lucidplan/domain.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/test/veritas/unit/planning-poker-spec.scm.go
;;; compiling test/veritas/unit/time-entry-spec.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/test/veritas/unit/time-entry-spec.scm.go
;;; compiling test/veritas/unit/ticket-triage-spec.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/test/veritas/unit/ticket-triage-spec.scm.go
;;; compiling test/veritas/unit/ticket-estimate-spec.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/test/veritas/unit/ticket-estimate-spec.scm.go
;;; compiling test/veritas/unit/ticket-thread-spec.scm
;;; compiling lib/lucidplan/domain/ticket-comment.scm
;;; compiling lib/lucidplan/domain/repo.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/lib/lucidplan/domain/repo.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/lib/lucidplan/domain/ticket-comment.scm.go
;;; compiling lib/lucidplan/attachments.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/lib/lucidplan/attachments.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/test/veritas/unit/ticket-thread-spec.scm.go
;;; compiling test/veritas/unit/burndown-spec.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/lucidplan/trunk/test/veritas/unit/burndown-spec.scm.go
;;; note: source file /etc/byggsteg/job-clone/lucidplan/trunk/maak.scm
;;;       newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.6/etc/byggsteg/job-clone/lucidplan/trunk/maak.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /etc/byggsteg/job-clone/lucidplan/trunk/maak.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.6/etc/byggsteg/job-clone/lucidplan/trunk/maak.scm.go


--------------------------------------------------------------

Maak 0.14.0: the infinitely extensible command runner

Loading tasks from Maak file: /etc/byggsteg/job-clone/lucidplan/trunk/maak.scm

Executing Maak tasks: test


--------------------------------------------------------------

=> Running Maak task: test

  Run the test suite with veritas.

The tests live under `test/veritas/': `unit/' for the ones that run on every
change, and `benchmark/' for the ones that measure rather than assert, which
veritas keeps apart because they answer a different question and take a
different amount of time.  The application's own directories are on the load
path, so a test names the module it tests the way the application does.

Executing: env VERITAS_TEST_TYPE=unit VERITAS_RUN_BENCHMARKS=true guix time-machine --channels=channels.scm -- shell -m manifest.scm -- guile --fresh-auto-compile -L . -L lib -L test -c '(begin (setlocale LC_ALL "C.UTF-8") (use-modules (veritas runner)) (run-tests))'

→ running command: cd /etc/byggsteg/job-clone/lucidplan/trunk && maak migrate

-------------------------------------------------
Starting Mutastructura: guile -L /gnu/store/dlg9fm51pz31zv0fbqq5svy7sh0dbs2h-profile/share/guile/site/3.0 -c ((@(mutastructura main) main)) --database sqlite3 --connection lucidplan.db --migrations /etc/byggsteg/job-clone/lucidplan/trunk/resources/migrations/sqlite --resources /gnu/store/dlg9fm51pz31zv0fbqq5svy7sh0dbs2h-profile/share/resources

---------------------------------------------------------
MUTASTRUCTURA: Schema Migrations tooling powered by Lisp

 🏛️  M U T A S T R U C T U R A  🏛️

 _ _ V E N I • V I D I • L I S P _ _


WARNING: Checksum mismatch for already applied migration 2026-04-01_10:52:00_init_lucidplan_schema.sql!

WARNING: Checksum mismatch for already applied migration 2026-05-22_11:21:00_drop_unique_constraint_human_id.sql!

WARNING: Checksum mismatch for already applied migration 2026-10-14_12:00:00_add_project_ticket_statuses.sql!

WARNING: Checksum mismatch for already applied migration 2026-10-22_12:00:00_add_ticket_estimates_collaboration_history.sql!

WARNING: Checksum mismatch for already applied migration 2026-10-27_12:00:00_add_sprints_milestones_time_entries.sql!

WARNING: Checksum mismatch for already applied migration 2026-10-27_13:00:00_add_planning_poker.sql!

WARNING: Checksum mismatch for already applied migration 2026-10-27_14:00:00_add_poker_item_ticket.sql!

WARNING: Checksum mismatch for already applied migration 2026-10-27_15:00:00_add_poker_room_ticket.sql!

FOUND MIGRATION HISTORY:

((id . 1) (name . "mutastructura-init.sql") (checksum . "9cc74e39062f44295eed10dcc318b67a87a2dc0ac9bc62eb76500fc4f3650e03") (applied-at . "2026-04-07 13:04:36"))

((id . 2) (name . "2026-04-01_10:52:00_init_lucidplan_schema.sql") (checksum . "f3923079248f1ffca1e9b06357e0a2207f07179609cbe24c44ab1108ed512593") (applied-at . "2026-04-07 13:11:37"))

((id . 3) (name . "2026-04-07_12:21:00_add_root_user.sql") (checksum . "7b09084eda456e679e753b07db590033604f1a92612160ab84f621405218b9b3") (applied-at . "2026-04-07 13:11:37"))

((id . 4) (name . "2026-05-22_11:21:00_drop_unique_constraint_human_id.sql") (checksum . "1ec83c352cd035fa547cc2f901ae01ab9dbb5c1cacb33d6fee2c683fa7f21e61") (applied-at . "2026-05-22 22:02:32"))

((id . 5) (name . "2026-10-14_12:00:00_add_project_ticket_statuses.sql") (checksum . "e3f1e0272a130ea622a137f106dbbd5986e85ae3732cfab84710f0e3cf53d867") (applied-at . "2026-10-14 11:52:12"))

((id . 6) (name . "2026-10-22_12:00:00_add_ticket_estimates_collaboration_history.sql") (checksum . "31de462a20b09362e9600ea0095f25285a87edf886bf29ef314b337014788dd3") (applied-at . "2026-10-22 18:30:25"))

((id . 7) (name . "2026-10-27_12:00:00_add_sprints_milestones_time_entries.sql") (checksum . "3e3c2a32f6c6871b78f74a8481f1c9bfeba95da302a9eab5f033b84cf5a33a4e") (applied-at . "2026-10-26 08:10:30"))

((id . 8) (name . "2026-10-27_13:00:00_add_planning_poker.sql") (checksum . "a3e14ee805b11306e176d4ec5c746b057633b8704034628afe0fdb749f01a1e5") (applied-at . "2026-10-27 20:24:22"))

((id . 9) (name . "2026-10-27_14:00:00_add_poker_item_ticket.sql") (checksum . "7b97f73c573ae9b4fc27d99429ef29bc5eb8e24790dd9a655543d9609a77d50f") (applied-at . "2026-10-27 20:24:22"))

((id . 10) (name . "2026-10-27_15:00:00_add_poker_room_ticket.sql") (checksum . "0b37bad93d5d9a4884765af4cf4e703df6991b5d207e0e88174398f9abb13792") (applied-at . "2026-10-27 20:24:22"))

((id . 11) (name . "2026-10-28_17:00:00_add_project_avatar.sql") (checksum . "80d4091f0ba7bc3be6678303f272f79bed9aa246ff5a4f2d535e772aa2764b27") (applied-at . "2026-10-28 19:33:34"))

((id . 12) (name . "2026-10-28_18:00:00_store_project_avatar_in_database.sql") (checksum . "6bbca6c6b86fcdbd1af22312c7f5da0f84d3d615c3389f3652420b765450b1df") (applied-at . "2026-10-28 19:33:34"))

((id . 13) (name . "2026-10-28_19:00:00_store_ticket_attachments_in_database.sql") (checksum . "287f4b621cac3766d5daa1ee2d9ea00668071a08c16e2c540f1b48ae60f7231a") (applied-at . "2026-10-28 19:33:34"))

((id . 14) (name . "2026-10-28_20:00:00_add_epics.sql") (checksum . "f5b3f8f655bdda335fed6ed4164917328a0f3911d8fa0a57caae082c4350d778") (applied-at . "2026-10-28 20:19:04"))

((id . 15) (name . "2026-10-28_21:00:00_add_labels_and_saved_filters.sql") (checksum . "0ab2d2f9dc0a0b2424907b378f69f6576959a210258f92f8100dc488f8851c93") (applied-at . "2026-10-28 20:19:04"))


---------------------------------------------------------
NOTHING TO DO!

CLOSING DATABASE...



--------------------------------------------------------------

Maak 0.14.0: the infinitely extensible command runner

Loading tasks from Maak file: /etc/byggsteg/job-clone/lucidplan/trunk/maak.scm

Executing Maak tasks: migrate


--------------------------------------------------------------

=> Running Maak task: migrate

  Bring the database up to the schema the migrations describe.

Every migration in the migrations directory that the ledger has not recorded
yet is applied, in filename order, each inside its own transaction; a
database that is already up to date is left alone, and one that is not is
never half-migrated, because a migration that fails takes its own statements
back with it.  The ledger is what makes that possible -- it is the record of
what has run, and mutastructura is the only thing that writes it -- so the
migrations are applied here and nowhere else, by hand or otherwise.

Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- mutastructura --database sqlite3 --connection lucidplan.db --migrations ./resources/migrations/sqlite

→ running command: cd /etc/byggsteg/job-clone/lucidplan/trunk && sudo maak deploy

Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required).  Falling back to plain text.  (see ‘org-html-htmlize-output-type’)
finished publishing Lucidplan manual


--------------------------------------------------------------

Maak 0.14.0: the infinitely extensible command runner

Loading tasks from Maak file: /etc/byggsteg/job-clone/lucidplan/trunk/maak.scm

Executing Maak tasks: deploy


--------------------------------------------------------------

=> Running Maak task: deploy

  Deploy the project's documentation.

  Execute command:
guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch --eval '(progn (require (quote ox-html)) (setq org-html-prefer-user-labels t) (find-file "./README.org") (org-html-export-to-html) (message "finished publishing Lucidplan manual"))'

Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch --eval '(progn (require (quote ox-html)) (setq org-html-prefer-user-labels t) (find-file "./README.org") (org-html-export-to-html) (message "finished publishing Lucidplan manual"))'
removed '/srv/http/jointhefreeworld.org/manuals/lucidplan/index.html'
renamed 'README.html' -> '/srv/http/jointhefreeworld.org/manuals/lucidplan/index.html'

→ running command: cd /etc/byggsteg/job-clone/lucidplan/trunk && sudo herd enable lucidplan-daemon || true && sudo herd restart lucidplan-daemon || true

Enabled service lucidplan-daemon.
Service lucidplan-daemon has been started.
inspect the job's lambda expression
(lambda()
  `((task . ("maak-test" "maak-migrate" "maak-deploy" "pull-and-restart"))
    (daemon-name . "lucidplan-daemon")
    (project . "lucidplan")
    (branch-name . "trunk")
    (clone-url . "https://github.com/jjba23/lucidplan.git")))