sift-283cd926-26ba

job succeeded

starting new job...


→ running command: dir='/etc/byggsteg/job-clone//sift/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 8258f12 to f4dc050

→ running command: cd /etc/byggsteg/job-clone/sift/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/sift/trunk && git log --name-status HEAD^..HEAD

commit f4dc050e46b485074ae0bb5188c012fba3e60b61
Author: Josep Bigorra <jjbigorra@gmail.com>
Date:   Tue Nov 3 10:09:19 2026 +0100

    chore(release): v1.20.0

M       .github/workflows/sift.yml
M       .pre-commit-hooks.yaml
M       README.org
M       action.yml
A       doc/cli.org
M       doc/editors.org
A       doc/language-server.org
M       doc/rules.org
M       editors/vscode/package.json
M       emacs/sift.el
M       src/sift/analysis.scm
M       src/sift/checkers/inference.scm
M       src/sift/lsp.scm
M       src/sift/records.scm
M       tests/lsp.scm

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

channels.scm:17:6: warning: channel 'jointhefreeworld' is not trusted
loading tests/catalogue.scm
;;; note: source file ./src/sift/records.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/records.go
;;; note: source file ./src/sift/records.scm
;;;       newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/records.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling ./src/sift/records.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/records.scm.go
;;; note: source file ./src/sift/lint.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/lint.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/lint.scm.go
;;; note: source file ./src/sift/reader.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/reader.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/reader.scm.go
;;; note: source file ./src/sift/pool.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/pool.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/pool.scm.go
;;; note: source file ./src/sift/check/base.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/check/base.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/check/base.scm.go
;;; note: source file ./src/sift/checkers/whitespace.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/whitespace.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/whitespace.scm.go
;;; note: source file ./src/sift/checkers/comments.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/comments.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/comments.scm.go
;;; note: source file ./src/sift/checkers/parens.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/parens.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/parens.scm.go
;;; note: source file ./src/sift/checkers/bodies.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/bodies.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/bodies.scm.go
;;; note: source file ./src/sift/checkers/scheme.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/scheme.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/scheme.scm.go
;;; note: source file ./src/sift/format.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/format.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/format.scm.go
;;; note: source file ./src/sift/imports.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/imports.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/imports.scm.go
;;; note: source file ./src/sift/checkers/elisp.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/elisp.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/elisp.scm.go
;;; note: source file ./src/sift/checkers/cl.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/cl.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/cl.scm.go
;;; note: source file ./src/sift/checkers/ergonomics.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/ergonomics.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/ergonomics.scm.go
;;; note: source file ./src/sift/checkers/naming.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/naming.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/naming.scm.go
;;; note: source file ./src/sift/checkers/simplify.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/simplify.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/simplify.scm.go
;;; note: source file ./src/sift/checkers/sxml.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/sxml.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/sxml.scm.go
;;; note: source file ./src/sift/checkers/practices.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/practices.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/practices.scm.go
;;; note: source file ./src/sift/checkers/inference.scm
;;;       newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/inference.scm.go
;;; compiling ./src/sift/checkers/inference.scm
;;; note: source file ./src/sift/definitions.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/definitions.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/definitions.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/inference.scm.go
;;; note: source file ./src/sift/catalogue.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/catalogue.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/catalogue.scm.go
;;; note: source file ./src/sift/config.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/config.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/config.scm.go
;;; note: source file ./src/sift/yaml.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/yaml.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/yaml.scm.go
loading tests/check-base.scm
loading tests/checkers/append-nothing.scm
loading tests/checkers/apply-of-list.scm
loading tests/checkers/assoc-ref-outputs.scm
loading tests/checkers/beta-reduction.scm
loading tests/checkers/blank-line-in-body.scm
loading tests/checkers/call-arity.scm
loading tests/checkers/case-literal-datum.scm
loading tests/checkers/checkdoc-style-verb.scm
loading tests/checkers/clause-brackets.scm
loading tests/checkers/comment-semicolons.scm
loading tests/checkers/composition.scm
loading tests/checkers/dangling-paren.scm
loading tests/checkers/declare-indent.scm
loading tests/checkers/defpackage-use.scm
loading tests/checkers/defun-no-docstring.scm
loading tests/checkers/docstring-arguments.scm
loading tests/checkers/docstring-first-line.scm
loading tests/checkers/docstring-indent.scm
loading tests/checkers/docstring-missing.scm
loading tests/checkers/docstring-texinfo.scm
loading tests/checkers/double-colon.scm
loading tests/checkers/ecase-otherwise.scm
loading tests/checkers/empty-body.scm
loading tests/checkers/empty-form.scm
loading tests/checkers/eq-nil.scm
loading tests/checkers/eq-non-symbol.scm
loading tests/checkers/eta-reduction.scm
loading tests/checkers/gexp-output-script.scm
loading tests/checkers/gexp-quoted.scm
loading tests/checkers/if-without-else.scm
loading tests/checkers/inputs-label-alist.scm
loading tests/checkers/interactive-without-arguments.scm
loading tests/checkers/interactive-without-docstring.scm
loading tests/checkers/internal-define.scm
loading tests/checkers/keyword-arguments.scm
loading tests/checkers/let-sibling.scm
loading tests/checkers/let-simplification.scm
loading tests/checkers/letrec-init-reference.scm
loading tests/checkers/letrec-single-binding.scm
loading tests/checkers/lexical-binding-missing.scm
loading tests/checkers/library-not-found.scm
loading tests/checkers/line-length.scm
loading tests/checkers/loop-keyword-style.scm
loading tests/checkers/mixed-lambda-list.scm
loading tests/checkers/naming-convention.scm
loading tests/checkers/needless-let-star.scm
loading tests/checkers/negated-if.scm
loading tests/checkers/nesting-depth.scm
loading tests/checkers/number-literal-argument.scm
loading tests/checkers/package-description-literal.scm
loading tests/checkers/package-prefix.scm
loading tests/checkers/package-synopsis.scm
loading tests/checkers/phase-name-quoting.scm
loading tests/checkers/practices.scm
loading tests/checkers/predicate-name.scm
loading tests/checkers/provide-missing.scm
loading tests/checkers/quasiquote-unquote-constant.scm
loading tests/checkers/reader-prefix-break.scm
loading tests/checkers/redundant-identity.scm
loading tests/checkers/redundant-progn.scm
loading tests/checkers/require-cl.scm
loading tests/checkers/save-excursion-set-buffer.scm
loading tests/checkers/sha256-base32.scm
loading tests/checkers/single-letter-name.scm
loading tests/checkers/special-variable-name.scm
loading tests/checkers/string-append-file-append.scm
loading tests/checkers/string-literal-argument.scm
loading tests/checkers/sxml-attributes.scm
loading tests/checkers/sxml-child.scm
loading tests/checkers/sxml-empty-element.scm
loading tests/checkers/tabs.scm
loading tests/checkers/trailing-blank-lines.scm
loading tests/checkers/trailing-whitespace.scm
loading tests/checkers/ungexp-outside-gexp.scm
loading tests/checkers/unless-without-body.scm
loading tests/checkers/unmatched-parens.scm
loading tests/checkers/unused-argument.scm
loading tests/checkers/unused-definition.scm
loading tests/checkers/unused-import-from.scm
loading tests/checkers/unused-import.scm
loading tests/checkers/use-modules-in-gexp.scm
loading tests/checkers/when-without-body.scm
loading tests/checkers/wrap-in-let.scm
loading tests/cli.scm
loading tests/declarations.scm
loading tests/definitions.scm
loading tests/files.scm
;;; note: source file ./src/sift/files.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/files.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/files.scm.go
loading tests/format-cl.scm
loading tests/format-elisp.scm
loading tests/format-scheme.scm
loading tests/gexp.scm
loading tests/json.scm
;;; note: source file ./src/sift/json.scm
;;;       newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/json.go

+----------------------------------------------+
[📑 suite] catalogue
  [🧪 test] every rule has a code
    ✅ got: ()
  [🧪 test] the summary table has a row per rule
    ✅ got: 92
  [🧪 test] every code looks like one
    ✅ got: ()
  [🧪 test] every rule has an example and a sentence about its fix
    ✅ got: ()
  [🧪 test] doc/rules.org is what the rules produce
    [⚙️ assert] doc/rules.org is up to date
    ✅ got: #t
  [🧪 test] no two rules share a code
    ✅ got: 92
  [🧪 test] the document names every rule by name and code
    ✅ got: ** SIFT068 append-nothing
    ✅ got: ** SIFT064 apply-of-list
    ✅ got: ** SIFT080 assoc-ref-outputs
    ✅ got: ** SIFT046 beta-reduction
    ✅ got: ** SIFT052 blank-line-in-body
    ✅ got: ** SIFT088 call-arity
    ✅ got: ** SIFT069 case-literal-datum
    ✅ got: ** SIFT022 checkdoc-style-verb
    ✅ got: ** SIFT036 clause-brackets
    ✅ got: ** SIFT051 comment-semicolons
    ✅ got: ** SIFT047 composition
    ✅ got: ** SIFT056 cond-else-not-last
    ✅ got: ** SIFT027 dangling-paren
    ✅ got: ** SIFT024 declare-indent
    ✅ got: ** SIFT059 defcustom-without-type
    ✅ got: ** SIFT071 defpackage-use
    ✅ got: ** SIFT028 defun-no-docstring
    ✅ got: ** SIFT034 docstring-arguments
    ✅ got: ** SIFT038 docstring-before-interactive
    ✅ got: ** SIFT018 docstring-first-line
    ✅ got: ** SIFT019 docstring-indent
    ✅ got: ** SIFT017 docstring-missing
    ✅ got: ** SIFT035 docstring-texinfo
    ✅ got: ** SIFT026 double-colon
    ✅ got: ** SIFT037 duplicate-binding
    ✅ got: ** SIFT057 duplicate-case-datum
    ✅ got: ** SIFT009 duplicate-keyword
    ✅ got: ** SIFT072 ecase-otherwise
    ✅ got: ** SIFT005 empty-body
    ✅ got: ** SIFT008 empty-form
    ✅ got: ** SIFT067 eq-nil
    ✅ got: ** SIFT092 eq-non-symbol
    ✅ got: ** SIFT055 eq-on-literal
    ✅ got: ** SIFT045 eta-reduction
    ✅ got: ** SIFT079 gexp-output-script
    ✅ got: ** SIFT077 gexp-quoted
    ✅ got: ** SIFT012 if-without-else
    ✅ got: ** SIFT087 inputs-label-alist
    ✅ got: ** SIFT076 interactive-without-arguments
    ✅ got: ** SIFT021 interactive-without-docstring
    ✅ got: ** SIFT011 internal-define
    ✅ got: ** SIFT032 keyword-arguments
    ✅ got: ** SIFT065 let-sibling
    ✅ got: ** SIFT048 let-simplification
    ✅ got: ** SIFT070 letrec-init-reference
    ✅ got: ** SIFT015 letrec-single-binding
    ✅ got: ** SIFT020 lexical-binding-missing
    ✅ got: ** SIFT061 library-not-found
    ✅ got: ** SIFT003 line-length
    ✅ got: ** SIFT029 loop-keyword-style
    ✅ got: ** SIFT073 mixed-lambda-list
    ✅ got: ** SIFT040 naming-convention
    ✅ got: ** SIFT066 needless-let*
    ✅ got: ** SIFT033 negated-if
    ✅ got: ** SIFT044 nesting-depth
    ✅ got: ** SIFT090 number-literal-argument
    ✅ got: ** SIFT085 package-description-literal
    ✅ got: ** SIFT025 package-prefix
    ✅ got: ** SIFT084 package-synopsis
    ✅ got: ** SIFT082 phase-name-quoting
    ✅ got: ** SIFT041 predicate-name
    ✅ got: ** SIFT023 provide-missing
    ✅ got: ** SIFT016 quasiquote-unquote-constant
    ✅ got: ** SIFT054 quote-of-constant
    ✅ got: ** SIFT007 reader-prefix-break
    ✅ got: ** SIFT030 redundant-identity
    ✅ got: ** SIFT006 redundant-progn
    ✅ got: ** SIFT074 require-cl
    ✅ got: ** SIFT075 save-excursion-set-buffer
    ✅ got: ** SIFT086 sha256-base32
    ✅ got: ** SIFT053 single-letter-name
    ✅ got: ** SIFT042 special-variable-name
    ✅ got: ** SIFT081 string-append-file-append
    ✅ got: ** SIFT089 string-literal-argument
    ✅ got: ** SIFT049 sxml-attributes
    ✅ got: ** SIFT050 sxml-child
    ✅ got: ** SIFT063 sxml-empty-element
    ✅ got: ** SIFT002 tabs
    ✅ got: ** SIFT058 too-many-arguments
    ✅ got: ** SIFT010 trailing-blank-lines
    ✅ got: ** SIFT001 trailing-whitespace
    ✅ got: ** SIFT078 ungexp-outside-gexp
    ✅ got: ** SIFT014 unless-without-body
    ✅ got: ** SIFT004 unmatched-parens
    ✅ got: ** SIFT043 unused-argument
    ✅ got: ** SIFT039 unused-binding
    ✅ got: ** SIFT062 unused-definition
    ✅ got: ** SIFT060 unused-import
    ✅ got: ** SIFT091 unused-import-from
    ✅ got: ** SIFT083 use-modules-in-gexp
    ✅ got: ** SIFT013 when-without-body
    ✅ got: ** SIFT031 wrap-in-let
+----------------------------------------------+
[📑 suite] walk: where code is evaluated
  [🧪 test] a `case` datum is data, and its clauses are code
    [⚙️ assert] the `case`, and the calls in the clause bodies
    ✅ got: (case f else g)
  [🧪 test] nothing inside a vector literal is code
    [⚙️ assert] the two calls, and neither literal
    ✅ got: (begin f)
  [🧪 test] a quoted form holds data, not code
    [⚙️ assert] only the call is a form
    ✅ got: (#t #f #f)
    [⚙️ assert] the call, `car`, and the quote mark
    ✅ got: 3
  [🧪 test] `walk-forms' and `code-position?' agree on every ambiguous source
    [⚙️ assert] "(quote (if a b))\n" agrees
    ✅ got: #t
    [⚙️ assert] "'(if a b)\n" agrees
    ✅ got: #t
    [⚙️ assert] "`(a ,(if b c) d)\n" agrees
    ✅ got: #t
    [⚙️ assert] "`(a ,@(if b (list c)) d)\n" agrees
    ✅ got: #t
    [⚙️ assert] "(case x\n  ((if a b) 1)\n  (else (if a b)))\n" agrees
    ✅ got: #t
    [⚙️ assert] "(define (f (if #f)) (if a b))\n" agrees
    ✅ got: #t
    [⚙️ assert] "(lambda (x) (lambda (y) y))\n" agrees
    ✅ got: #t
    [⚙️ assert] "#(if a b)\n" agrees
    ✅ got: #t
    [⚙️ assert] "#u8(1 2 3)\n" agrees
    ✅ got: #t
    [⚙️ assert] "(define x #(1 #(2 (if a b))))\n" agrees
    ✅ got: #t
    [⚙️ assert] "(let loop ((i 0)) (when (< i 1) (loop (+ i 1))))\n" agrees
    ✅ got: #t
    [⚙️ assert] "(define-syntax m (syntax-rules () ((_ a) a)))\n" agrees
    ✅ got: #t
    [⚙️ assert] "#'(a b)\n" agrees
    ✅ got: #t
    [⚙️ assert] "(syntax-case stx ()\n  ((_ a) #'a))\n" agrees
    ✅ got: #t
    [⚙️ assert] "(case x\n  ((a b) 1)\n  (else 2))\n" agrees
    ✅ got: #t
    [⚙️ assert] "(defun f (x) \"doc\" (if x y z))\n" agrees
    ✅ got: #t
    [⚙️ assert] "(defmacro m (a) `(list ,a))\n" agrees
    ✅ got: #t
    [⚙️ assert] "#+foo (if a b)\n" agrees
    ✅ got: #t
    [⚙️ assert] "(quasiquote (a (unquote (if x y))))\n" agrees
    ✅ got: #t
    [⚙️ assert] "; a comment\n(if a b)\n" agrees
    ✅ got: #t
  [🧪 test] an unquote is code again
    [⚙️ assert] the two forms inside unquotes, and nothing else
    ✅ got: (if list)
  [🧪 test] a parameter list holds parameters, not forms
    [⚙️ assert] the definition and the call, not the default's `g`
    ✅ got: (define g)
+----------------------------------------------+
[📑 suite] checker: append-nothing
  [🧪 test] the fixed files have nothing left to report
    [⚙️ assert] "(append xs '())\n" is clean after its fix
    ✅ got: ()
    [⚙️ assert] "(append '() xs)\n" is clean after its fix
    ✅ got: ()
    [⚙️ assert] "(append '(1) '() '(2))\n" is clean after its fix
    ✅ got: ()
  [🧪 test] accepts an append with no empty list
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the empty list may come first
    [⚙️ assert] the fix produces the expected text
    ✅ got: xs

  [🧪 test] the fix is the other list
    [⚙️ assert] the fix produces the expected text
    ✅ got: xs

  [🧪 test] the empty list may sit between two others
    [⚙️ assert] the fix produces the expected text
    ✅ got: (append '(1) '(2))

  [🧪 test] reports an append of the empty list
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: apply-of-list
  [🧪 test] accepts an apply of a variable
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a list argument that is not the last one
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an apply of the empty list
    [⚙️ assert] the fix produces the expected text
    ✅ got: (f)

  [🧪 test] the fixed files have nothing left to report
    [⚙️ assert] "(apply f 1 (list 2 3))\n" is clean after its fix
    ✅ got: ()
    [⚙️ assert] "(apply f '())\n" is clean after its fix
    ✅ got: ()
  [🧪 test] the fix writes the call
    [⚙️ assert] the fix produces the expected text
    ✅ got: (f 1 2 3)

  [🧪 test] an Emacs Lisp apply is the same apply
    [⚙️ assert] the fix produces the expected text
    ✅ got: ('f 1 2)

  [🧪 test] reports an apply of a list
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: assoc-ref-outputs
  [🧪 test] leaves a lookup outside a build body alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports the alist in a quasiquoted build body
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a quasiquote outside a derivation is an ordinary list
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] that body's fix writes `%output`
    [⚙️ assert] the fix produces the expected text
    ✅ got: (gexp->derivation "x" `(mkdir %output))

  [🧪 test] accepts a lookup of a build input
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports the alist lookup inside a gexp
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] accepts `#$output`
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix writes `#$output`
    [⚙️ assert] the fix produces the expected text
    ✅ got: #~(mkdir #$output)

    [⚙️ assert] the fixed text is clean
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: beta-reduction
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] the fix writes the let
    [⚙️ assert] the fix produces the expected text
    ✅ got: (let ((x (g))) (f x))

  [🧪 test] reports a lambda applied in place
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] a multi-form body becomes a multi-form let
    [⚙️ assert] the fix produces the expected text
    ✅ got: (let ((x (h))) (f x) (g x))

  [🧪 test] a Common Lisp lambda applied in place is a let too
    [⚙️ assert] the fix produces the expected text
    ✅ got: (let ((x (g))) (f x))

  [🧪 test] accepts a call to something that is not a lambda
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a lambda applied to two arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a lambda with no body
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: blank-line-in-body
  [🧪 test] reports a run of blank lines as one finding
    [⚙️ assert] the findings are where they should be
    ✅ got: ((5 3))
  [🧪 test] reports a blank line between two body forms of a definition
    [⚙️ assert] the findings are where they should be
    ✅ got: ((4 3))
  [🧪 test] reports a blank line in a `lambda' body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((4 3))
  [🧪 test] accepts a blank line between two internal definitions
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a blank line between top-level forms
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a blank line between the forms of an Emacs Lisp defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ((4 3))
  [🧪 test] accepts a blank line between the bindings of a `let'
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a body whose forms are adjacent
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a blank line in a `let' body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((4 3))
+----------------------------------------------+
[📑 suite] checker: call-arity
  [🧪 test] reads &body of a Common Lisp macro as a rest parameter
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reads the parameters of a Common Lisp definition
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reports a call with too few arguments
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reads &optional, &rest, &key and &aux in Common Lisp
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reports a keyword the definition does not take
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a named let is a procedure whose parameters are its variables
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reads &optional and &rest in Emacs Lisp
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] optional, keyword and rest parameters are not required
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] an optional parameter with a default is still one argument
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a key parameter is passed by keyword, not positionally
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a binding of the same name is not the definition
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a rest parameter does not lower the floor
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a procedure bound in a let is counted, not the top-level one
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a definition inside a body is the one a call in it means
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a case-lambda clause list with a gap reports the counts it takes
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reports a keyword with no value
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reports a keyword to a definition that takes none
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] an optional parameter raises the ceiling
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a rest parameter takes as many arguments as a caller has
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a name defined twice accepts what either definition accepts
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a call inside a quote is data
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a call with too many arguments
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a case-lambda is right when some clause accepts the call
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] allow-other-keys takes the keyword set away
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] counts a definition whose value is a lambda
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a call with every argument
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: case-literal-datum
  [🧪 test] accepts symbols and characters
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a string datum
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 11))
  [🧪 test] accepts a nullary case with a default
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a string datum written without a list
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
+----------------------------------------------+
[📑 suite] checker: checkdoc-style-verb
  [🧪 test] accepts the imperative
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a third-person opening
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
+----------------------------------------------+
[📑 suite] checker: clause-brackets
  [🧪 test] accepts a cond clause written with square brackets
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a cond clause written with parentheses
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 7) (2 7))
  [🧪 test] says nothing when the project preserves what was written
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] the default for the other dialects is to preserve
    ✅ got: preserve
    ✅ got: preserve
  [🧪 test] follows a project that writes parentheses
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 7))
  [🧪 test] the default for Scheme is square
    ✅ got: square
  [🧪 test] reports a case clause written with parentheses
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 9) (2 3))
  [🧪 test] the fix rewrites the delimiters
    [⚙️ assert] the fix produces the expected text
    ✅ got: (cond [(= x 1) 'one]
      [else 'other])

+----------------------------------------------+
[📑 suite] checker: comment-semicolons
  [🧪 test] reports a top-level comment with two semicolons
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fix leaves a heading at four semicolons
    [⚙️ assert] the fix produces the expected text
    ✅ got: ;;;; Frob Grovel
(define x 1)

  [🧪 test] reports a comment with no space after its semicolons
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fix leaves a margin comment alone
    [⚙️ assert] the fix produces the expected text
    ✅ got: (a b) ;Zibblefrotz.

  [🧪 test] reports a heading inside a form, where two is the level
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] says nothing about a block comment, which has no semicolons
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a margin comment with one semicolon
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix leaves the sentence of the comment exactly as it was
    [⚙️ assert] the fix produces the expected text
    ✅ got: ;;; spaced  out  
(define x 1)

  [🧪 test] accepts a heading, which has four
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts two semicolons inside a form
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix raises a top-level comment to three semicolons
    [⚙️ assert] the fix produces the expected text
    ✅ got: ;;; about the program
(define x 1)

  [🧪 test] one pass fixes every comment in the buffer
    [⚙️ assert] the fix produces the expected text
    ✅ got: ;;; first
(define (f x)
  ;; second
  x)
;;; third

  [🧪 test] the fix adds the space after the semicolons and nothing else
    [⚙️ assert] the fix produces the expected text
    ✅ got: ;;; tight
(define x 1)

  [🧪 test] reports a one-semicolon comment inside a form
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] the fix lowers a comment inside a form to two semicolons
    [⚙️ assert] the fix produces the expected text
    ✅ got: (define (f x)
  ;; a heading in a body
  x)

  [🧪 test] accepts a top-level comment with three semicolons
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fixed buffer is clean, so a second run has nothing to do
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] accepts a margin comment written without a space
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: composition
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] does not suggest Guile's compose to Common Lisp
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts an inner call that takes more than the argument
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix names the composition
    [⚙️ assert] the fix produces the expected text
    ✅ got: (compose f g)

  [🧪 test] accepts a lambda that takes two arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a lambda whose body is one call around another
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts a body that is not a nested call
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: dangling-paren
  [🧪 test] accepts a closer that trails the last element
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] the fix pulls the closer onto the previous line
    [⚙️ assert] the fix produces the expected text
    ✅ got: (defun f (x)
  x)

  [🧪 test] reports a closer that starts a line
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 3))
+----------------------------------------------+
[📑 suite] checker: declare-indent
  [🧪 test] accepts a declare two columns in
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix re-indents the declare
    [⚙️ assert] the fix produces the expected text
    ✅ got: (defun f (x)
  (declare (indent 1))
  x)

  [🧪 test] reports a declare indented too far
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 5))
+----------------------------------------------+
[📑 suite] checker: defpackage-use
  [🧪 test] accepts :import-from
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a package that only uses :cl
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a :use of a library other than :cl
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 29))
  [🧪 test] reports each library it finds
    [⚙️ assert] the number of findings is right
    ✅ got: 2
+----------------------------------------------+
[📑 suite] checker: defun-no-docstring
  [🧪 test] reports a defun with no docstring
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts a documented defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: docstring-arguments
  [🧪 test] says nothing about a defun with no docstring
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] looks through optional and rest arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] accepts a docstring that names its arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts any spelling of the name
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports each argument the docstring does not mention
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3) (2 3))
+----------------------------------------------+
[📑 suite] checker: docstring-first-line
  [🧪 test] accepts a capitalised sentence with a period
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a first line that is too long for apropos
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] reports a first line that starts lowercase
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] reports a first line with no full stop
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
+----------------------------------------------+
[📑 suite] checker: docstring-indent
  [🧪 test] accepts continuation lines that start at column zero
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an indented continuation line
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
+----------------------------------------------+
[📑 suite] checker: docstring-missing
  [🧪 test] a defun with no body is a finding, not a crash
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] reports a defcustom with no docstring
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] reports a defun with no docstring
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts a documented defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a bare defvar declaration
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a defvar with no docstring
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: docstring-texinfo
  [🧪 test] reports each undocumented parameter
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] reports a parameter the docstring does not document
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] says nothing about a procedure with no parameters
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a docstring that documents every parameter
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] says nothing about a definition with no docstring
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: double-colon
  [🧪 test] accepts an ordinary symbol
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a double-colon reference
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
  [🧪 test] accepts a single-colon reference
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: ecase-otherwise
  [🧪 test] reports an otherwise clause in etypecase
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 26))
  [🧪 test] reports a t clause in ecase
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 16))
  [🧪 test] accepts an ecase that covers its cases
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a default clause in case, which is what case is for
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: empty-body
  [🧪 test] reports a cond with no clauses
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] covers when and unless in Emacs Lisp
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] reports a cond clause with no body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 7))
  [🧪 test] reports a lambda with no body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] a case datum is data, not a form
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a form with a body
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a let with no body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: empty-form
  [🧪 test] accepts an empty binding list
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts the literals list of a syntax-rules transformer
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a quoted empty list
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts the literals list of a syntax-case transformer
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts an empty parameter list
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports the empty list in an argument position
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 7))
+----------------------------------------------+
[📑 suite] checker: eq-nil
  [🧪 test] a Common Lisp eq against nil asks null
    [⚙️ assert] the fix produces the expected text
    ✅ got: (null y)

  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] accepts a comparison with #f
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] an Emacs Lisp eq against nil asks null
    [⚙️ assert] the fix produces the expected text
    ✅ got: (null x)

  [🧪 test] the fix asks null?
    [⚙️ assert] the fix produces the expected text
    ✅ got: (null? x)

  [🧪 test] reports an eq? against the empty list
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts a comparison with another symbol
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: eq-non-symbol
  [🧪 test] `memq` of a string asks for `member`
    [⚙️ assert] the fix produces the expected text
    ✅ got: (member "a" xs)

  [🧪 test] accepts a symbol, which identity does decide
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix writes `eqv?`
    [⚙️ assert] the fix produces the expected text
    ✅ got: (eqv? x 1)

    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] reports `eq?` against a number
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
  [🧪 test] accepts two variables
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a string asks for `equal?`
    [⚙️ assert] the fix produces the expected text
    ✅ got: (equal? x "a")

  [🧪 test] Common Lisp asks for `eql`
    [⚙️ assert] the fix produces the expected text
    ✅ got: (eql x 1.0)

+----------------------------------------------+
[📑 suite] checker: eta-reduction
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] reports a lambda that only passes its argument on
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fix names the procedure itself
    [⚙️ assert] the fix produces the expected text
    ✅ got: f

  [🧪 test] an Emacs Lisp lambda is not a Scheme function designator
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a body that is more than the call
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a call that passes something else
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a rest argument
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a lambda with two formals
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a call that passes more than the argument
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] never rewrites a special form into a value
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: gexp-output-script
  [🧪 test] reports `#$output` in a `gexp->script`
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 30))
  [🧪 test] accepts `#$output` in a derivation
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts another ungexp in a file-making gexp
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports `#$output` in a `program-file`
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 33))
+----------------------------------------------+
[📑 suite] checker: gexp-quoted
  [🧪 test] reports a gexp under a quasiquote
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 8))
  [🧪 test] accepts a gexp where it is used
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a gexp written under a quote
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 12))
  [🧪 test] accepts the long-hand `gexp`
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: if-without-else
  [🧪 test] what an unquote puts back is code again
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 17))
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 22))
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 18))
  [🧪 test] a vector literal is data, not a form
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a quasiquoted or quasisyntaxed template is data
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an if with two arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
  [🧪 test] the fix rewrites it as when
    [⚙️ assert] the fix produces the expected text
    ✅ got: (when a b)

  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] accepts an if with an else branch
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: inputs-label-alist
  [🧪 test] reports a labelled input list
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] leaves an alist outside a package alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix writes the list of packages
    [⚙️ assert] the fix produces the expected text
    ✅ got: (package (inputs (list gawk)))

    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] reports the other two input lists as well
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] accepts a list of packages
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: interactive-without-arguments
  [🧪 test] accepts optional parameters, which may be left out
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a command with no parameters
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a spec that supplies the argument
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a command with a required argument and an empty spec
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 3))
+----------------------------------------------+
[📑 suite] checker: interactive-without-docstring
  [🧪 test] reports an interactive command with no docstring
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] accepts a documented command
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: internal-define
  [🧪 test] reports a define inside a lambda, after an expression
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 3))
  [🧪 test] accepts definitions at the head of a body
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts top-level definitions
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a definition under a let
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a define that comes after the first expression
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 3))
+----------------------------------------------+
[📑 suite] checker: keyword-arguments
  [🧪 test] a project names its own record macros
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] an operating-system is a record too
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a call with too many positional arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts arguments that are already keywords
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the export list of a define-module is data
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a special form
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a call with a readable number of arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a Common Lisp package definition is a declaration
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a parameter list is not a call
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a use-modules form is a declaration, not a call
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fields of a record macro are still linted
    [⚙️ assert] the findings are where they should be
    ✅ got: ((4 12))
  [🧪 test] require and provide are declarations
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the limit is configuration
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts the calls that are meant to be variadic
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a Guix package is a record, not a call with too many arguments
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: let-sibling
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] reports an initializer that reaches for a sibling
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 18))
  [🧪 test] accepts a name that only appears under a quote
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a mention an inner scope binds again
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a reference from a lambda body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 18))
  [🧪 test] the fix says let*
    [⚙️ assert] the fix produces the expected text
    ✅ got: (let* ((a (f)) (b (g a))) b)

  [🧪 test] accepts independent initializers
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: let-simplification
  [🧪 test] the fix is the body
    [⚙️ assert] the fix produces the expected text
    ✅ got: (f)

  [🧪 test] accepts a binding that is used in the body
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix is the value
    [⚙️ assert] the fix produces the expected text
    ✅ got: (f)

  [🧪 test] accepts a let with two bindings
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a let with a named let
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix says let
    [⚙️ assert] the fix produces the expected text
    ✅ got: (let ((x (f))) (g x))

  [🧪 test] reports a let* that binds once
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
  [🧪 test] reports a binding that exists to be returned
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fixed files have nothing left to report
    [⚙️ assert] "(let ((x (f))) x)\n" is clean after its fix
    ✅ got: ()
    [⚙️ assert] "(let () (f))\n" is clean after its fix
    ✅ got: ()
    [⚙️ assert] "(let* ((x (f))) (g x))\n" is clean after its fix
    ✅ got: ()
  [🧪 test] reports a let with no bindings
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts a let* with two bindings
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] an Emacs Lisp let is the same let
    [⚙️ assert] the fix produces the expected text
    ✅ got: (f)

+----------------------------------------------+
[📑 suite] checker: letrec-init-reference
  [🧪 test] accepts a self-reference inside a lambda
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts mutually recursive procedures
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an initializer that refers to a binding
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 19))
  [🧪 test] accepts initializers that mention nothing the form binds
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: letrec-single-binding
  [🧪 test] reports a letrec with one non-recursive binding
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts a binding that refers to itself
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts two bindings
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: lexical-binding-missing
  [🧪 test] accepts a header on the second line
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a file with no header
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fix inserts the header
    [⚙️ assert] the fix produces the expected text
    ✅ got: ;;; -*- lexical-binding: t; -*-
;;; f.el --- a package

  [🧪 test] accepts a header on the first line
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: library-not-found
  [🧪 test] a project that declares no library is not judged
    ✅ got: ()
  [🧪 test] a library imported where nothing it exports is used is reported
    ✅ got: ((1 23))
  [🧪 test] a standard library is never reported missing
    ✅ got: ()
  [🧪 test] a library the file declares itself is found
    ✅ got: ()
  [🧪 test] a library the project declares is found
    ✅ got: ()
  [🧪 test] an import of a library no file declares is reported
    ✅ got: ((1 23))
+----------------------------------------------+
[📑 suite] checker: line-length
  [🧪 test] reports a line over the Scheme limit
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 97))
  [🧪 test] accepts a short line
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a line over the Emacs Lisp limit, which is 80
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 81))
  [🧪 test] the limit can be configured
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 6))
+----------------------------------------------+
[📑 suite] checker: loop-keyword-style
  [🧪 test] says nothing when both spellings are accepted
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix rewrites the keywords
    [⚙️ assert] the fix produces the expected text
    ✅ got: (loop :for x :in xs :do (print x))

  [🧪 test] reports symbolic keywords when the style asks for literal ones
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 7) (1 13) (1 19))
+----------------------------------------------+
[📑 suite] checker: mixed-lambda-list
  [🧪 test] reports a lambda that takes both
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 9))
  [🧪 test] accepts keywords alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a plain lambda list
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts optionals alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a defun that takes both
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
+----------------------------------------------+
[📑 suite] checker: naming-convention
  [🧪 test] reports a capitalised name
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] reports a Common Lisp defparameter
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 15))
  [🧪 test] reports an underscore in a procedure name
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] reports a variable definition too
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 9))
  [🧪 test] accepts the usual hyphenated name
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a name that is punctuation
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] says nothing about a symbol that is not a definition
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an Emacs Lisp defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 8))
  [🧪 test] reports camelCase in a procedure name
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
+----------------------------------------------+
[📑 suite] checker: needless-let*
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] an Emacs Lisp let* is the same let*
    [⚙️ assert] the fix produces the expected text
    ✅ got: (let ((a (f)) (b (g))) (+ a b))

  [🧪 test] accepts a let* with one binding, which is another rule's
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix says let
    [⚙️ assert] the fix produces the expected text
    ✅ got: (let ((a (f)) (b (g))) (+ a b))

  [🧪 test] reports a let* whose bindings are independent
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
  [🧪 test] accepts a let* that depends on its own order
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: negated-if
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] reports a when with a negated test
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fix rewrites a when as an unless
    [⚙️ assert] the fix produces the expected text
    ✅ got: (unless x (go))

  [🧪 test] accepts an if whose test is not a negation
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix rewrites the if as an unless
    [⚙️ assert] the fix produces the expected text
    ✅ got: (unless (ready?) (wait) (go))

  [🧪 test] reports an if with a negated test and no else branch
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts an unless
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an if with a negated test
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: nesting-depth
  [🧪 test] accepts a `let' inside a `cond' inside a `define'
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] counts a `when' inside an `if'
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] reports a chain of conditionals deeper than the limit
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the limit is configuration
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: number-literal-argument
  [🧪 test] reports a string compared with a number
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] leaves a variable alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a string added to a number
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] accepts numbers
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] does not read `string-append` as arithmetic
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: package-description-literal
  [🧪 test] reports a description built with `string-append`
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 23))
  [🧪 test] accepts a literal description
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a package with no description field
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a description built with `format`
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 23))
+----------------------------------------------+
[📑 suite] checker: package-prefix
  [🧪 test] accepts a prefixed use
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an exported symbol used without a prefix
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 2))
  [🧪 test] accepts a file with no export list
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: package-synopsis
  [🧪 test] leaves a `synopsis` outside a package alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a synopsis that starts in lower case
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 20))
  [🧪 test] accepts a synopsis as the manual asks for it
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a synopsis that opens with an article and ends with a period
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 31) (1 31))
+----------------------------------------------+
[📑 suite] checker: phase-name-quoting
  [🧪 test] reports a phase named by a string
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 42))
  [🧪 test] accepts quoted names in `add-before` and `add-after`
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix quotes it
    [⚙️ assert] the fix produces the expected text
    ✅ got: (modify-phases %standard-phases (delete 'configure))

    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] leaves a `replace` outside `modify-phases` alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an unquoted phase name
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 41))
+----------------------------------------------+
[📑 suite] checker: practices
  [🧪 test] a quoted number is reported and the quote is removable
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the fix produces the expected text
    ✅ got: 5

    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] only the required positional parameters are counted
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the number of findings is right
    ✅ got: 0
  [🧪 test] six parameters are reported and five are not
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a quote around a symbol is left alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a defcustom without :type is reported in Emacs Lisp
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a defun's parameters are all of them, not all but the first
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a cond with clauses after else is reported
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] eq? on a number and on a string are reported
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] a quoted string, character and list are told apart
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] eq? on two variables and eqv? on a number are silent
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a case datum listed twice is reported
    [⚙️ assert] the number of findings is right
    ✅ got: 1
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: predicate-name
  [🧪 test] reports a procedure that returns a comparison
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] Emacs Lisp reports a name with neither suffix
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 8))
  [🧪 test] reports a procedure whose last form is another predicate
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] accepts a procedure that returns something else
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] Emacs Lisp accepts the -p suffix
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a docstring is not the returned value
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] accepts a name that ends in a question mark
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: provide-missing
  [🧪 test] accepts a file that provides its feature
    [⚙️ assert] the number of findings is right
    ✅ got: 0
  [🧪 test] accepts a file that defines nothing
    [⚙️ assert] the number of findings is right
    ✅ got: 0
  [🧪 test] reports a file that defines but never provides
    [⚙️ assert] the number of findings is right
    ✅ got: 1
+----------------------------------------------+
[📑 suite] checker: quasiquote-unquote-constant
  [🧪 test] reports an unquoted number inside a quasiquote
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 5))
  [🧪 test] reports the long-hand form too
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 13))
  [🧪 test] accepts an unquoted variable
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: reader-prefix-break
  [🧪 test] a function quote is covered too
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fix joins the prefix to the datum
    [⚙️ assert] the fix produces the expected text
    ✅ got: '(a)

  [🧪 test] reports a quote separated from its datum
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts a quote attached to its datum
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: redundant-identity
  [🧪 test] accepts a plain call
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an identity call
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 21))
  [🧪 test] reports a funcall of a function name
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: redundant-progn
  [🧪 test] a vector whose first element is progn is a literal, not a body
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] accepts a progn with company
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports one in a defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 13))
  [🧪 test] reports a progn that is the only body form
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 13))
  [🧪 test] the fix splices the body
    [⚙️ assert] the fix produces the expected text
    ✅ got: (define (f) (a) (b))

+----------------------------------------------+
[📑 suite] checker: require-cl
  [🧪 test] accepts another library
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports the pieces of cl as well
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts cl-lib
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a require of cl
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: save-excursion-set-buffer
  [🧪 test] reports one nested in a body form
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 25))
  [🧪 test] accepts an excursion that changes nothing
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a set-buffer inside save-excursion
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 17))
  [🧪 test] accepts with-current-buffer around an excursion
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: sha256-base32
  [🧪 test] leaves a `sha256` outside an origin alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts 52 lower-case characters
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a base32 string of the wrong length
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 17))
  [🧪 test] reports a hash that is not written in base32
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 17))
  [🧪 test] reports a hash with an upper-case character
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 17))
+----------------------------------------------+
[📑 suite] checker: single-letter-name
  [🧪 test] reports each single-letter parameter of a definition
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 15) (1 17))
  [🧪 test] reports a parameter of a `lambda'
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
  [🧪 test] says nothing about a definition that names a program
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts an index variable, which is what the setting is for
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts names made of words
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts an ignored parameter
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports the binding of a `let'
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 8))
  [🧪 test] reports a parameter of a Common Lisp defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 11))
  [🧪 test] reports a parameter of an Emacs Lisp defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 11))
  [🧪 test] the accepted names are a setting
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a setting replaces the default list rather than extending it
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 10))
+----------------------------------------------+
[📑 suite] checker: special-variable-name
  [🧪 test] reports a Common Lisp constant without plus signs
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 14))
  [🧪 test] reports a Common Lisp special variable without earmuffs
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 15))
  [🧪 test] accepts an earmuffed one
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a plain Emacs Lisp variable
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a constant written with plus signs
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports earmuffs in Emacs Lisp
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 9))
+----------------------------------------------+
[📑 suite] checker: string-append-file-append
  [🧪 test] accepts the output directory, which is not a package
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a run-time `string-append` in a gexp
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 12))
  [🧪 test] reports it in a quasiquoted build body
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] the fix writes `file-append`
    [⚙️ assert] the fix produces the expected text
    ✅ got: #~(system* #$(file-append coreutils "/bin/ls"))

    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] and leaves that body as it found it
    [⚙️ assert] the fix produces the expected text
    ✅ got: (gexp->derivation "x" `(system* (string-append ,coreutils "/bin/ls")))

  [🧪 test] accepts `file-append`
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] leaves a `string-append` outside a build body alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: string-literal-argument
  [🧪 test] accepts strings
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] does not read an index as a string
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] leaves a variable alone, whatever it holds
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports the character position a comparison takes
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 15))
  [🧪 test] reports a number passed to `string-append`
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reports a boolean passed to `string-length`
    [⚙️ assert] the number of findings is right
    ✅ got: 1
+----------------------------------------------+
[📑 suite] checker: sxml-attributes
  [🧪 test] reports an empty attribute list
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 6))
  [🧪 test] reports a second attribute list
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 22))
  [🧪 test] accepts an element whose attributes come first
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts an element with no attributes at all
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports attributes that come after a child
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 14))
  [🧪 test] accepts a document of nested elements
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: sxml-child
  [🧪 test] accepts the same list without the extra level
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts elements, strings and numbers as children
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a list of elements where elements belong
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 18))
  [🧪 test] an element with no attributes is not judged
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: sxml-empty-element
  [🧪 test] the fix keeps the layout the element was written with
    [⚙️ assert] the fix produces the expected text
    ✅ got: (div
  (@ (class "card")) "")

  [🧪 test] accepts the same element with an empty text child
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fixed text is clean
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] accepts an element with a child
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts an element with no attributes at all
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports the inner element of a document
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 19))
  [🧪 test] a comment inside the element does not make it a parent
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] the fix writes the child that closes the element
    [⚙️ assert] the fix produces the expected text
    ✅ got: (div (@ (class "my-2 px-3")) "")

  [🧪 test] reports every empty element, not only the outermost
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 6) (3 6))
  [🧪 test] leaves a repeated attribute list to the rule that names it
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] leaves an empty attribute list to the rule that names it
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an element with attributes and nothing else
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: tabs
  [🧪 test] accepts indentation made of spaces
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix replaces the tab with spaces
    [⚙️ assert] the fix produces the expected text
    ✅ got: (a
  b)

  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] a tab inside a string is data, not indentation
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a tab used for indentation
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 1))
+----------------------------------------------+
[📑 suite] checker: trailing-blank-lines
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] accepts a file with a single trailing newline
    [⚙️ assert] the number of findings is right
    ✅ got: 0
  [🧪 test] the fix trims the end of the file to one blank line
    [⚙️ assert] the fix produces the expected text
    ✅ got: (define x 1)


  [🧪 test] accepts a file with one blank line at the end
    [⚙️ assert] the number of findings is right
    ✅ got: 0
  [🧪 test] reports four blank lines at the end of a file
    [⚙️ assert] the number of findings is right
    ✅ got: 1
+----------------------------------------------+
[📑 suite] checker: trailing-whitespace
  [🧪 test] the fixed file has nothing left to report
    [⚙️ assert] the fixed text is clean
    ✅ got: ()
  [🧪 test] accepts a file whose lines are clean
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix strips the whitespace
    [⚙️ assert] the fix produces the expected text
    ✅ got: x
y

  [🧪 test] reports every line of a file
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2) (2 2))
  [🧪 test] reports a line that ends with a tab
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
  [🧪 test] reports a line that ends with a space
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
+----------------------------------------------+
[📑 suite] checker: ungexp-outside-gexp
  [🧪 test] reports `#$` with no gexp around it
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 7))
  [🧪 test] accepts the long-hand forms inside `gexp`
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a gexp that lost its `#~`
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 11))
  [🧪 test] reports `#+@` with no gexp around it
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 7))
  [🧪 test] accepts every form inside a gexp
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: unless-without-body
  [🧪 test] reports an unless with no body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] accepts an unless with a body
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports one in Common Lisp too
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: unmatched-parens
  [🧪 test] reports a stray closing parenthesis
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 2))
  [🧪 test] accepts a balanced file
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports an unmatched opening parenthesis at the opener
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1) (1 4))
+----------------------------------------------+
[📑 suite] checker: unused-argument
  [🧪 test] reports a parameter the body never uses
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 14))
  [🧪 test] accepts a parameter that is used
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reads the parameters of a defun
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 13))
  [🧪 test] accepts a lambda that uses its parameter
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reads a parameter with a default
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 25))
  [🧪 test] reads a specialized Common Lisp parameter
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 19))
  [🧪 test] accepts a parameter named with an underscore
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: unused-definition
  [🧪 test] reports a definition nothing uses and the module does not export
    [⚙️ assert] the findings are where they should be
    ✅ got: ((4 10))
  [🧪 test] a definition another one uses is not dead
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a module that says it exports nothing is judged
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 10))
  [🧪 test] the name in the export list is the name that counts
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 10))
  [🧪 test] a name mentioned under a quote counts as mentioned
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a module with no #:export clause is not judged
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a file with no define-module is not judged
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] an exported definition is the module's surface
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: unused-import-from
  [🧪 test] reports an imported name the file never uses
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] reads every name of the clause
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] accepts an imported name the file uses
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a package with no import clause is fine
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: unused-import
  [🧪 test] a name used only inside a quote does not count as used
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] an `only` clause with nothing used is one finding, on the form
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] every name in an `only` clause used is silent
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a renamed import nothing uses, by its new name
    [⚙️ assert] the fix produces the expected text
    ✅ got: (import (rename (srfi 1) (fold foldl)))
(display (foldl + 0 (list 1)))

  [🧪 test] the fix removes the whole import when it is the only thing on its line
    [⚙️ assert] the fix produces the expected text
    ✅ got: (display 1)

  [🧪 test] a name used inside a template that spells unquote counts as used
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a name used inside a quasiquote counts as used
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] a plain import of a library sift cannot read is left alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] the fix deletes the name and the space before it
    [⚙️ assert] the fix produces the expected text
    ✅ got: (import (only (srfi 1) fold))
(display (fold + 0 (list 1 2)))

  [🧪 test] a `#:use-module` clause nothing uses is reported, keyword and all
    [⚙️ assert] one finding, on the clause
    ✅ got: 1
    [⚙️ assert] the fix removes the clause and the line it was on
    ✅ got: (define-module (proj client)
  #:export (f))
(define (f x) x)

  [🧪 test] an import used inside a library body is read
    [⚙️ assert] the findings are where they should be
    ✅ got: ((3 25))
  [🧪 test] a `#:use-module` clause whose names are used is silent
    [⚙️ assert] the name the clause brings in is used
    ✅ got: 0
  [🧪 test] one unused spec of two is deleted, and the form stays
    [⚙️ assert] the fix produces the expected text
    ✅ got: (import (scheme base))
(display 1)

  [🧪 test] reports the name of an `only` clause nothing uses
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 29))
+----------------------------------------------+
[📑 suite] checker: use-modules-in-gexp
  [🧪 test] accepts the extension modules too
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] leaves a library of the host stratum alone
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a build module imported inside a bare gexp
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 3))
  [🧪 test] reports it in a quasiquoted build body
    [⚙️ assert] the number of findings is right
    ✅ got: 1
  [🧪 test] accepts a body the builder was given the modules for
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] accepts a gexp marked with `with-imported-modules`
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] checker: when-without-body
  [🧪 test] accepts a when with a body
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a when with no body in Common Lisp
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
  [🧪 test] reports a when with no body
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: wrap-in-let
  [🧪 test] accepts a body form that is already split up
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] reports a body form with too many elements
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] reports a body form that nests too deeply
    [⚙️ assert] the findings are where they should be
    ✅ got: ((2 3))
  [🧪 test] the depth limit is configuration
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
  [🧪 test] there is no automatic fix
    ✅ got: #f
  [🧪 test] the element limit is configuration
    [⚙️ assert] the findings are where they should be
    ✅ got: ()
+----------------------------------------------+
[📑 suite] cli
  [🧪 test] install-hooks leaves an existing hook alone
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: already exists
  [🧪 test] a parse error is a refusal, with status 2
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: parse error
  [🧪 test] fix refuses a file that does not parse, and says why
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: parse error
    [⚙️ assert] the file is left exactly as it was
    ✅ got: (define (f x)
  (a b

  [🧪 test] version prints the version and succeeds
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: sift 
  [🧪 test] lint --format=json carries the rule code
    ✅ got: "code"
    ✅ got: SIFT001
  [🧪 test] --label names the source in diagnostics
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: my-buffer.scm
  [🧪 test] lint on a clean file succeeds and prints a summary
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: 1 file checked
  [🧪 test] --stdin with one file is the label, and is not a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 0
  [🧪 test] ci fails when a file is not formatted
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: @@ 
  [🧪 test] format writes the formatted source to stdout
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: (define (square x)
  (* x x))

(define (classify n)
  (cond [(< n 0) 'negative]
        [(= n 0) 'zero]
        [else 'positive]))

(let ((a 1)
      (b 2))
  (+ a b (* a b)))

  [🧪 test] lint --exclude-checker skips the checker it names
    ✅ got: trailing-whitespace
  [🧪 test] install-hooks --force replaces one
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: sift
  [🧪 test] fix --stdin refuses a buffer that does not parse
    [⚙️ assert] the exit status is right
    ✅ got: 2
    [⚙️ assert] no text is written to standard output
    ✅ got: 
  [🧪 test] doctor says what ran and what it decided
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] doctor starts with the version
    ✅ got: sift 
    ✅ got: rules
    ✅ got: sift.yaml
  [🧪 test] fix is lint --fix
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: (when (ready?) (go))

  [🧪 test] lint --format=sarif writes a SARIF document
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: "version":"2.1.0"
    ✅ got: "rules":
    ✅ got: "ruleId":"SIFT001"
    ✅ got: "artifactLocation"
  [🧪 test] lint reports findings with status 1
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: [trailing-whitespace]
  [🧪 test] lint --format=github writes workflow commands
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: ::warning file=
    ✅ got: title=SIFT001 [trailing-whitespace]
  [🧪 test] doctor names the library without a `..' in it
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the library line is a directory under the checkout
    ✅ got: /src
    ✅ got: ..
  [🧪 test] --stdin and --stdout work as a filter
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: (define (f x)
  (+ x 1))

  [🧪 test] ci --format=github turns formatting differences into annotations
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: ::error file=
  [🧪 test] lint --quiet keeps the findings and drops the summary
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: [trailing-whitespace]
    ✅ got: file checked
  [🧪 test] list-checkers prints each rule's code
    ✅ got: SIFT001
    ✅ got: CODE
  [🧪 test] lint --format=null says nothing at all
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] the text matches
    ✅ got: 
  [🧪 test] ci does not write the file it is judging
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] the text matches
    ✅ got: (define (f x)
  (+ x 1))   

  [🧪 test] ci passes on a clean file
    [⚙️ assert] the exit status is right
    ✅ got: 0
  [🧪 test] lint --format=sarif describes the rules, the artifacts and the run
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] the document carries "fullDescription":
    ✅ got: "fullDescription":
    [⚙️ assert] the document carries "help":{"text":
    ✅ got: "help":{"text":
    [⚙️ assert] the document carries "helpUri":
    ✅ got: "helpUri":
    [⚙️ assert] the document carries "shortDescription":
    ✅ got: "shortDescription":
    [⚙️ assert] the document carries "invocations":[{"executionSuccessful":true}]
    ✅ got: "invocations":[{"executionSuccessful":true}]
    [⚙️ assert] the document carries "artifacts":[{"location":{"uri":"tests/fixtures/lint/dirty.scm"}
    ✅ got: "artifacts":[{"location":{"uri":"tests/fixtures/lint/dirty.scm"}
    [⚙️ assert] the document carries "roles":["analysisTarget"]
    ✅ got: "roles":["analysisTarget"]
    [⚙️ assert] the document carries "index":0
    ✅ got: "index":0
    [⚙️ assert] the document carries "columnKind":"unicodeCodePoints"
    ✅ got: "columnKind":"unicodeCodePoints"
    [⚙️ assert] the document carries "partialFingerprints":{"siftFingerprint/v1":
    ✅ got: "partialFingerprints":{"siftFingerprint/v1":
    [⚙️ assert] the document carries "charOffset":
    ✅ got: "charOffset":
    [⚙️ assert] the document carries "charLength":
    ✅ got: "charLength":
    [⚙️ assert] the document carries "ruleIndex":0
    ✅ got: "ruleIndex":0
    [⚙️ assert] the rule is named by its code
    ✅ got: "ruleId":"SIFT001"
  [🧪 test] lint --fix rewrites the file and reports what is left
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: (when (ready?) (go))

  [🧪 test] list-checkers --dialect filters to the dialect
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: docstring-missing
    ✅ got: internal-define
  [🧪 test] explain documents a checker
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: DESCRIPTION
    ✅ got: DIALECTS
  [🧪 test] an unreadable file says why, in words
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: no-such-file.scm
    ✅ got: ~A
  [🧪 test] --write with --stdout is a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: cannot be used together
  [🧪 test] ci refuses to fix
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: never fixes
  [🧪 test] an unknown command is a usage error, with status 2
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: Usage:
  [🧪 test] check on an already formatted file succeeds
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: 
  [🧪 test] --brackets=parens overrides the Scheme default
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: (cond ((< n 0) 1)
  [🧪 test] explain answers 2 for a checker it does not know
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: unknown checker
  [🧪 test] --stdin with more than one file is a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: at most one file
  [🧪 test] an unreadable file is a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: cannot read
  [🧪 test] --version prints the version without a subcommand
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: sift 
  [🧪 test] lint --fix --stdin prints the fixed source to stdout
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: (when (ready?) (go))

  [🧪 test] format --diff on a formatted file prints nothing and exits 0
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: 
  [🧪 test] lint --format=json emits one array for the run
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] it starts with an array
    ✅ got: #t
    ✅ got: "severity"
    ✅ got: "checker"
    ✅ got: "line"
  [🧪 test] explain leads with the rule's code
    ✅ got: SIFT012
  [🧪 test] config show prints the effective configuration
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: line-length
    ✅ got: style
  [🧪 test] an unknown bracket style is a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: unknown bracket style
  [🧪 test] --force formats what can be read
    [⚙️ assert] the exit status is right
    ✅ got: 0
  [🧪 test] ci fails when the linter has something to say
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: [trailing-whitespace]
  [🧪 test] fix --force fixes what it can read
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] the trailing whitespace is gone
    ✅ got: (define (f x)

  [🧪 test] an unknown checker is a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: unknown checker
  [🧪 test] format --write rewrites the file in place
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: (define (f x)
  (+ x 1))

  [🧪 test] check reports a difference with status 1
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: @@ 
  [🧪 test] install-hooks outside a repository is a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: no git repository
  [🧪 test] an unknown dialect is a usage error
    [⚙️ assert] the exit status is right
    ✅ got: 2
    ✅ got: unknown dialect
  [🧪 test] a directory operand skips entries it cannot ask about
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] the file that could be read was read
    ✅ got: real.scm
  [🧪 test] install-hooks writes a pre-commit hook
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the hook was written
    ✅ got: #t
    ✅ got: sift
  [🧪 test] every option that takes a value accepts both spellings
    [⚙️ assert] --dialect value is accepted
    ✅ got: 0
    [⚙️ assert] --dialect spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

    [⚙️ assert] --severity value is accepted
    ✅ got: 0
    [⚙️ assert] --severity spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

    [⚙️ assert] --format value is accepted
    ✅ got: 0
    [⚙️ assert] --format spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

    [⚙️ assert] --style value is accepted
    ✅ got: 0
    [⚙️ assert] --style spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

    [⚙️ assert] --line-length value is accepted
    ✅ got: 0
    [⚙️ assert] --line-length spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

    [⚙️ assert] --indent value is accepted
    ✅ got: 0
    [⚙️ assert] --indent spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

    [⚙️ assert] --brackets value is accepted
    ✅ got: 0
    [⚙️ assert] --brackets spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

    [⚙️ assert] --label value is accepted
    ✅ got: 0
    [⚙️ assert] --label spells the same both ways
    ✅ got: (define (f x)
  (+ x 1))

  [🧪 test] a document format answers a run of several files once
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] it is one array
    ✅ got: #t
    [⚙️ assert] one array holds them all
    ✅ got: 1
  [🧪 test] lint --checker runs only the checker it names
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: trailing-whitespace
  [🧪 test] config explain documents a key
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: --line-length
  [🧪 test] list-checkers prints a table
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: trailing-whitespace
    ✅ got: SEVERITY
  [🧪 test] format --diff prints a patch and exits 1
    [⚙️ assert] the exit status is right
    ✅ got: 1
    ✅ got: @@ 
    ✅ got: -
  [🧪 test] a document format writes one document for the whole run
    [⚙️ assert] the exit status is right
    ✅ got: 1
    [⚙️ assert] there is one document
    ✅ got: 1
    [⚙️ assert] both files are artifacts
    ✅ got: 2
    ✅ got: "ruleId":"format"
    ✅ got: "ruleId":"SIFT001"
+----------------------------------------------+
[📑 suite] project configuration
  [🧪 test] indent-rules written as a YAML sequence indents the macro
    [⚙️ assert] the exit status is right
    ✅ got: 0
    [⚙️ assert] the text matches
    ✅ got: (with-my-thing
  (a)
  (b))

  [🧪 test] the inlay hints a project asks for are readable in YAML
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: inlay-hints: [parameters, types]
  [🧪 test] and off is a shape the setting accepts
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: inlay-hints: []
  [🧪 test] an empty flow sequence is an empty list of names
    [⚙️ assert] the exit status is right
    ✅ got: 0
    ✅ got: exclude-checkers: []
+----------------------------------------------+
[📑 suite] declarations: a declaration is not a call
  [🧪 test] a definition's body is still read as code
    ✅ got: 1
  [🧪 test] a parameter list is not a call, however long it is
    [⚙️ assert] elisp parameter list: (defun demo-f (a b c d e f g)
    ✅ got: ()
    [⚙️ assert] elisp parameter list: (lambda (a b c d e f g) (list a b c d e f g))
    ✅ got: ()
    [⚙️ assert] scheme parameter list: (define (demo-f a b c d e f g)
    ✅ got: ()
    [⚙️ assert] scheme parameter list: (define* (demo-g a b #:key c d e f g h)
    ✅ got: ()
    [⚙️ assert] cl parameter list: (defmethod area ((shape circle) &key (scale 1) &allow-other-keys)
    ✅ got: ()
  [🧪 test] a parameter list of keywords and optionals is not a call
    ✅ got: ()
  [🧪 test] a call with too many positional arguments is still reported
    ✅ got: 1
  [🧪 test] no rule about calls reports a declaration
    [⚙️ assert] scheme declaration: (define-module (demo thing)
    ✅ got: ()
    [⚙️ assert] scheme declaration: (use-modules (srfi srfi-1)
    ✅ got: ()
    [⚙️ assert] scheme declaration: (import (scheme base)
    ✅ got: ()
    [⚙️ assert] scheme declaration: (export one
    ✅ got: ()
    [⚙️ assert] scheme declaration: (define-library (demo lib)
    ✅ got: ()
    [⚙️ assert] scheme declaration: (library (demo r6rs)
    ✅ got: ()
    [⚙️ assert] scheme declaration: (declare (pure? #t) (blocked #:all) (names one two three four five six))
    ✅ got: ()
    [⚙️ assert] elisp declaration: (require 'cl-lib)
    ✅ got: ()
    [⚙️ assert] elisp declaration: (use-package flymake
    ✅ got: ()
    [⚙️ assert] elisp declaration: (declare-function sift-mode "sift" (&optional arg))
    ✅ got: ()
    [⚙️ assert] elisp declaration: (eval-when-compile (require 'cl-lib))
    ✅ got: ()
    [⚙️ assert] elisp declaration: (setq one 1 two 2 three 3 four 4 five 5 six 6)
    ✅ got: ()
    [⚙️ assert] cl declaration: (defpackage :demo
    ✅ got: ()
    [⚙️ assert] cl declaration: (in-package :demo)
    ✅ got: ()
    [⚙️ assert] cl declaration: (declaim (optimize (speed 3) (safety 0) (debug 0) (space 0) (compilation-speed 0)))
    ✅ got: ()
    [⚙️ assert] cl declaration: (proclaim '(ftype (function (fixnum fixnum) fixnum) add))
    ✅ got: ()
    [⚙️ assert] cl declaration: (defmethod area ((shape circle) &key (scale 1) &allow-other-keys)
    ✅ got: ()
    [⚙️ assert] cl declaration: (defun add (a b &optional (c 1) &key (d 2) &allow-other-keys)
    ✅ got: ()
  [🧪 test] a parameter list with too many required parameters is still reported
    ✅ got: 1
+----------------------------------------------+
[📑 suite] definitions: scope and bindings
  [🧪 test] a named let binds its own name over the body
    ✅ got: (loop 2 8)
  [🧪 test] a renamed ellipsis binds nothing either
    ✅ got: #f
  [🧪 test] an internal definition is a definition of the body it sits in
    ✅ got: (g 2 12)
  [🧪 test] a binding inside a template still wins over the pattern
    ✅ got: (tmp 4 13)
  [🧪 test] let-syntax binds its keyword over the body
    ✅ got: (with-two 1 15)
  [🧪 test] a parameter is nearer than the definition of the same name
    ✅ got: (x 1 12)
  [🧪 test] a literal in the pattern binds nothing
    ✅ got: #f
  [🧪 test] letrec-syntax binds its keyword over the body too
    ✅ got: (with-two 1 18)
  [🧪 test] the ellipsis binds nothing
    ✅ got: #f
  [🧪 test] a define-syntax is a macro in the outline
    ✅ got: ((swap! macro))
  [🧪 test] a syntax-case clause binds its pattern variables
    ✅ got: (a 3 7)
  [🧪 test] a let binding wins over the definition it shadows
    ✅ got: (x 2 10)
  [🧪 test] a pattern variable is not a definition of the file
    ✅ got: 1
  [🧪 test] a template variable is defined by its pattern
    ✅ got: (a 3 9)
  [🧪 test] a pattern variable inside a nested list is still a variable
    ✅ got: (a 3 10)
  [🧪 test] an underscore binds nothing
    ✅ got: #f
  [🧪 test] the name of a definition is a definition of itself
    ✅ got: (f 1 10)
+----------------------------------------------+
[📑 suite] files: extensions and filters
  [🧪 test] a pattern with no separator is matched against the file's own name
    ✅ got: #t
  [🧪 test] a filter replaces the extensions
    ✅ got: #t
    ✅ got: #f
  [🧪 test] * stops at a separator
    ✅ got: #f
    ✅ got: #t
  [🧪 test] a file sift has no extension for is not one of its files
    ✅ got: #f
  [🧪 test] a list of patterns is read as it is written
    ✅ got: (src/** !gen/**)
  [🧪 test] a single pattern is a filter with one rule
    ✅ got: (*.scm)
  [🧪 test] ** crosses a separator
    ✅ got: #t
  [🧪 test] a negated pattern takes a file back out
    ✅ got: #f
    ✅ got: #t
  [🧪 test] a pattern is read relative to the root of the walk
    ✅ got: #t
  [🧪 test] no filter in the file is no filter at all
    ✅ got: #f
  [🧪 test] the Scheme extensions sift reads include the library and program ones
    [⚙️ assert] .scm is a Lisp file
    ✅ got: #t
    [⚙️ assert] .ss is a Lisp file
    ✅ got: #t
    [⚙️ assert] .sld is a Lisp file
    ✅ got: #t
    [⚙️ assert] .sls is a Lisp file
    ✅ got: #t
    [⚙️ assert] .sps is a Lisp file
    ✅ got: #t
    [⚙️ assert] .el is a Lisp file
    ✅ got: #t
    [⚙️ assert] .lisp is a Lisp file
    ✅ got: #t
    [⚙️ assert] .cl is a Lisp file
    ✅ got: #t
    [⚙️ assert] .asd is a Lisp file
    ✅ got: #t
  [🧪 test] no filter falls back to the extensions
    ✅ got: #t
    ✅ got: #f
  [🧪 test] a dot in a pattern is a dot, not any character
    ✅ got: #f
  [🧪 test] the last pattern that matches decides
    ✅ got: #t
+----------------------------------------------+
[📑 suite] format: Common Lisp
  [🧪 test] formatting Common Lisp is idempotent
    [⚙️ assert] formatting is a fixed point
    ✅ got: (defun f (x)
  "Doc."
  (list x))

  [🧪 test] handler-case clauses align under each other
    [⚙️ assert] the text matches
    ✅ got: (handler-case (foo)
  (error (e)
    (print e)))
  [🧪 test] a LOOP keeps its keyword atoms and indents them two in
    [⚙️ assert] the text matches
    ✅ got: (loop :for x :in xs
  :do (print x))
  [🧪 test] a defpackage indents its clauses two columns in
    [⚙️ assert] the text matches
    ✅ got: (defpackage :demo
  (:use :cl)
  (:export #:run))
  [🧪 test] a defclass indents its slots two columns in
    [⚙️ assert] the text matches
    ✅ got: (defclass point ()
  ((x :initarg :x)
   (y :initarg :y)))
  [🧪 test] feature conditionals keep both halves on one line
    [⚙️ assert] the text matches
    ✅ got: #+sbcl (defun f ())
#-sbcl (defun f ())
  [🧪 test] every fixture formats to its expected file
    [⚙️ assert] package.lisp formats to its expected file
    ✅ got: (defpackage :demo
  (:use :cl)
  (:export #:run))

(in-package :demo)

(defun run (n)
  (loop :for i :below n
    :do (print i)))

    [⚙️ assert] reader-macros.lisp formats to its expected file
    ✅ got: (in-package :demo)

(defparameter *grid* #2A((1 2)
                         (3 4)))
(defparameter *z* #c(1 2))
(defparameter *cycle* #1=(a . #1#))
(probe-file #P"/tmp/x")

  [🧪 test] every expected file is a fixed point of formatting
    [⚙️ assert] package.lisp is already formatted
    ✅ got: (defpackage :demo
  (:use :cl)
  (:export #:run))

(in-package :demo)

(defun run (n)
  (loop :for i :below n
    :do (print i)))

    [⚙️ assert] reader-macros.lisp is already formatted
    ✅ got: (in-package :demo)

(defparameter *grid* #2A((1 2)
                         (3 4)))
(defparameter *z* #c(1 2))
(defparameter *cycle* #1=(a . #1#))
(probe-file #P"/tmp/x")

  [🧪 test] a read macro keeps the datum it applies to glued to it
    [⚙️ assert] the text matches
    ✅ got: (defparameter *a* #2A((1 2)))

    [⚙️ assert] the text matches
    ✅ got: (defparameter *c* #c(1 2))

    [⚙️ assert] the text matches
    ✅ got: (probe-file #P"/tmp/x")

  [🧪 test] line endings are normalised to LF
    [⚙️ assert] the text matches
    ✅ got: (a b)

+----------------------------------------------+
[📑 suite] format: Emacs Lisp
  [🧪 test] a read macro keeps the datum it applies to glued to it
    [⚙️ assert] the text matches
    ✅ got: (defvar t #s(hash-table test equal data ("a" 1)))
    [⚙️ assert] the text matches
    ✅ got: (defvar c #1=(a . #1#))
  [🧪 test] a let binds in a data list, lined up under the first binding
    [⚙️ assert] the text matches
    ✅ got: (let ((a 1)
      (b 2))
  (+ a b))
  [🧪 test] condition-case indents its protected form and handlers two in
    [⚙️ assert] the text matches
    ✅ got: (condition-case nil
  (foo)
  (error (message "no")))
  [🧪 test] formatting Emacs Lisp is idempotent
    [⚙️ assert] formatting is a fixed point
    ✅ got: (defun f (x)
  "Doc."
  (list x))

  [🧪 test] every expected file is a fixed point of formatting
    [⚙️ assert] buffer.el is already formatted
    ✅ got: ;;; buffer.el --- a demo -*- lexical-binding: t; -*-

(defun my-greet (name)
  "Greet NAME."
  (message "Hello, %s" name))

(let ((x 1)
      (y 2))
  (+ x y))

(provide 'buffer)

    [⚙️ assert] reader-macros.el is already formatted
    ✅ got: ;;; reader-macros.el --- the read macros of the dialect -*- lexical-binding: t; -*-

(defun my-setup ()
  "Set up the table and the keys."
  (setq my-table #s(hash-table test equal data ("a" 1)))
  (setq my-cycle #1=(a . #1#))
  (setq my-keys [?\C-x ?\C-c]))

(provide 'reader-macros)
(setq my-rx (rx (| "a" "b")))

    [⚙️ assert] use-package.el is already formatted
    ✅ got: ;;; use-package.el --- a demo -*- lexical-binding: t; -*-

(use-package evil
  :ensure t
  :init
  (setq evil-want-integration t)
  :config
  (evil-mode 1))

(use-package magit
  :ensure t
  :bind
  ("C-x g" . magit-status))

(use-package foo
  :ensure t
  :custom
  (foo-directory "/tmp/foo")
  :hook
  (prog-mode . foo-mode))

(provide 'use-package-demo)

  [🧪 test] a defun indents its docstring and body two columns in
    [⚙️ assert] the text matches
    ✅ got: (defun f (x)
  "Return X."
  (when x
    (message "x")))
  [🧪 test] documented forms the table knows are indented from the opener
    [⚙️ assert] the text matches
    ✅ got: (with-current-buffer buf
  (goto-char (point-min)))
  [🧪 test] every fixture formats to its expected file
    [⚙️ assert] buffer.el formats to its expected file
    ✅ got: ;;; buffer.el --- a demo -*- lexical-binding: t; -*-

(defun my-greet (name)
  "Greet NAME."
  (message "Hello, %s" name))

(let ((x 1)
      (y 2))
  (+ x y))

(provide 'buffer)

    [⚙️ assert] reader-macros.el formats to its expected file
    ✅ got: ;;; reader-macros.el --- the read macros of the dialect -*- lexical-binding: t; -*-

(defun my-setup ()
  "Set up the table and the keys."
  (setq my-table #s(hash-table test equal data ("a" 1)))
  (setq my-cycle #1=(a . #1#))
  (setq my-keys [?\C-x ?\C-c]))

(provide 'reader-macros)
(setq my-rx (rx (| "a" "b")))

    [⚙️ assert] use-package.el formats to its expected file
    ✅ got: ;;; use-package.el --- a demo -*- lexical-binding: t; -*-

(use-package evil
  :ensure t
  :init
  (setq evil-want-integration t)
  :config
  (evil-mode 1))

(use-package magit
  :ensure t
  :bind
  ("C-x g" . magit-status))

(use-package foo
  :ensure t
  :custom
  (foo-directory "/tmp/foo")
  :hook
  (prog-mode . foo-mode))

(provide 'use-package-demo)

  [🧪 test] the square bracket style does not reach Emacs Lisp
    [⚙️ assert] the text matches
    ✅ got: (cond ((null x) 1)
      (t 2))
  [🧪 test] a data list whose head starts a line is not aligned past it
    [⚙️ assert] the text matches
    ✅ got: (defcustom x
  '(
    insert-tab))
  [🧪 test] strings, escapes and characters are preserved
    [⚙️ assert] the text matches
    ✅ got: (message "a  b\n" ?\C-x)
  [🧪 test] a use-package form puts its keywords and their bodies two columns in
    [⚙️ assert] the text matches
    ✅ got: (use-package evil
  :ensure t
  :init
  (setq evil-want-integration t)
  :config
  (evil-mode 1))
  [🧪 test] use-package keywords do not line up under the package name
    [⚙️ assert] the text matches
    ✅ got: (use-package magit
  :ensure t
  :bind
  ("C-x g" . magit-status))
+----------------------------------------------+
[📑 suite] format: Scheme
  [🧪 test] blank lines between top-level forms are collapsed to one
    [⚙️ assert] the text matches
    ✅ got: (a)

(b)

  [🧪 test] moving a verbatim block is idempotent
    [⚙️ assert] the shifted block is the same on the second pass
    ✅ got: (define (f)
  #;(ignore
  this)
  x)

  [🧪 test] a read macro keeps the datum it applies to glued to it
    [⚙️ assert] the text matches
    ✅ got: (define a #1=(x . #1#))

    [⚙️ assert] the text matches
    ✅ got: (display #`(a #,b #,@c))

  [🧪 test] a vector's elements line up under its first, symbol or not
    [⚙️ assert] the text matches
    ✅ got: (define v #(foo bar
            baz))

  [🧪 test] two forms on one line are separated when asked
    [⚙️ assert] the text matches
    ✅ got: (a)

(b)

  [🧪 test] comments are aligned when asked
    [⚙️ assert] the text matches
    ✅ got: (let ((a 1)   ; one
      (b 22)) ; two
  (+ a b))

  [🧪 test] a file without a final newline keeps that shape
    [⚙️ assert] the text matches
    ✅ got: (a b)
  [🧪 test] a comment keeps the line it was on
    [⚙️ assert] the text matches
    ✅ got: (a ; inline
 b)

  [🧪 test] a list whose first element starts a line indents one column in
    [⚙️ assert] the text matches
    ✅ got: '(
  insert-tab)

  [🧪 test] a vector keeps its own opener whatever the bracket style is
    [⚙️ assert] the text matches
    ✅ got: #(1 2 3)
  [🧪 test] every fixture formats to its expected file
    [⚙️ assert] comments.scm formats to its expected file
    ✅ got: ;;; A file about comments.
(define (f x) ; inline
  ;; standalone
  x) ; trailing

;; a comment after a blank line
(display "text")

    [⚙️ assert] messy.scm formats to its expected file
    ✅ got: (define (square x)
  (* x x))

(define (classify n)
  (cond [(< n 0) 'negative]
        [(= n 0) 'zero]
        [else 'positive]))

(let ((a 1)
      (b 2))
  (+ a b (* a b)))

    [⚙️ assert] reader-macros.scm formats to its expected file
    ✅ got: '(a b)
`(c ,d ,@e)
#(1 2 3) #u8(1 2)
#;(ignored   form)
#| block |#
#+(or a b) (display "x")
(define table #(one two
                three))
(define bytes #vu8(1 2))
(define #{odd name}# 'x)
(define-syntax (m stx)
  (syntax-case stx ()
    [(_ x) #`(list #,x ,x)]))
(define (f lst' x'') (list lst' x''))

  [🧪 test] the body of a clause indents two columns
    [⚙️ assert] the text matches
    ✅ got: (cond [else
        1])
  [🧪 test] an R6RS library indents its declarations two columns in
    [⚙️ assert] the text matches
    ✅ got: #!r6rs
(library (demo)
  (export f)
  (import (rnrs)))

    [⚙️ assert] the text matches
    ✅ got: #!fold-case
(define-library (demo lib)
  (import (scheme base))
  (export a))

  [🧪 test] an unknown operator lines its arguments up under the first
    [⚙️ assert] the text matches
    ✅ got: (my-macro a
          b)

  [🧪 test] preserving brackets leaves each clause as it was written
    [⚙️ assert] the text matches
    ✅ got: (cond ((< n 0) 1)
      [else 2])
  [🧪 test] one blank line separates adjacent top-level forms when asked
    [⚙️ assert] the text matches
    ✅ got: (a)

(b)

  [🧪 test] a multi-line datum comment moves with the code around it
    [⚙️ assert] the text matches
    ✅ got: (define (f)
  #;(ignore
  this)
  x)

  [🧪 test] a blank line inside a form is kept, but a run is collapsed to two
    [⚙️ assert] the text matches
    ✅ got: (a


 b)

  [🧪 test] indentation follows the operator's rule
    [⚙️ assert] the text matches
    ✅ got: (define (f x)
  (let ((a 1))
    (if x
      a
      x)))

  [🧪 test] a multi-line extended symbol keeps the name it was given
    [⚙️ assert] the text matches
    ✅ got: (define #{what
ever}# 1)

  [🧪 test] a bytevector's numbers line up under the first as well
    [⚙️ assert] the text matches
    ✅ got: (define b #u8(1 2
              3))

    [⚙️ assert] the text matches
    ✅ got: (define b #vu8(1 2
               3))

  [🧪 test] a single-line datum comment is untouched
    [⚙️ assert] the text matches
    ✅ got: (a #;(b c) d)
  [🧪 test] a reader prefix is never separated from its datum
    [⚙️ assert] the text matches
    ✅ got: 'a

  [🧪 test] a cond whose clauses start on their own lines indents them two in
    [⚙️ assert] the text matches
    ✅ got: (cond
  [(< n 0) 1]
  [else 2])
  [🧪 test] the dangling style puts each closer on its own line
    [⚙️ assert] nested.scm formats to its expected file
    ✅ got: (define (f x)
  (let ((a 1)
        (b 2)
       )
    (when (> a b)
      (display "yes")
    )
  )
)

    [⚙️ assert] nested.scm is already formatted
    ✅ got: (define (f x)
  (let ((a 1)
        (b 2)
       )
    (when (> a b)
      (display "yes")
    )
  )
)

  [🧪 test] a heading comment stays with the form it heads
    [⚙️ assert] the text matches
    ✅ got: (a)

;;; b
(b)

  [🧪 test] an extended symbol is one token, and is never respelled
    [⚙️ assert] the text matches
    ✅ got: (define #{foo bar}# 1)

  [🧪 test] keyword arguments line up under the first argument
    [⚙️ assert] the text matches
    ✅ got: (make-window title
             :width 10
             :height 20)
  [🧪 test] a vector is closed with the delimiter it was opened with
    [⚙️ assert] the text matches
    ✅ got: (define v #(a b))

  [🧪 test] the one-blank-line style is a fixed point
    [⚙️ assert] the text matches
    ✅ got: (a)

(b)

  [🧪 test] every expected file is a fixed point of formatting
    [⚙️ assert] comments.scm is already formatted
    ✅ got: ;;; A file about comments.
(define (f x) ; inline
  ;; standalone
  x) ; trailing

;; a comment after a blank line
(display "text")

    [⚙️ assert] messy.scm is already formatted
    ✅ got: (define (square x)
  (* x x))

(define (classify n)
  (cond [(< n 0) 'negative]
        [(= n 0) 'zero]
        [else 'positive]))

(let ((a 1)
      (b 2))
  (+ a b (* a b)))

    [⚙️ assert] reader-macros.scm is already formatted
    ✅ got: '(a b)
`(c ,d ,@e)
#(1 2 3) #u8(1 2)
#;(ignored   form)
#| block |#
#+(or a b) (display "x")
(define table #(one two
                three))
(define bytes #vu8(1 2))
(define #{odd name}# 'x)
(define-syntax (m stx)
  (syntax-case stx ()
    [(_ x) #`(list #,x ,x)]))
(define (f lst' x'') (list lst' x''))

  [🧪 test] cond clauses are written with square brackets
    [⚙️ assert] the text matches
    ✅ got: (cond [(< n 0) 'negative]
      [(= n 0) 'zero]
      [else 'positive])
  [🧪 test] an unknown operator alone on its line indents one column in
    [⚙️ assert] the text matches
    ✅ got: (my-macro
 a)

  [🧪 test] a data list lines up under its first element
    [⚙️ assert] the text matches
    ✅ got: (let ((a 1)
      (b 2))
  (+ a b))

  [🧪 test] a project's own indent rule wins over the table
    [⚙️ assert] the text matches
    ✅ got: (with-my-thing x
    y)
  [🧪 test] a project's own indent rule is idempotent
    [⚙️ assert] the project rule formats the same way twice
    ✅ got: (with-my-thing x
               y)

  [🧪 test] a call without keywords lines up the same way
    [⚙️ assert] the text matches
    ✅ got: (make-window title
             width
             height)
  [🧪 test] formatting is idempotent on this sentence's own source
    [⚙️ assert] formatting is a fixed point
    ✅ got: (define (f x) (progn (a) (b)))

  [🧪 test] preserve adds no blank line the author did not write
    [⚙️ assert] the text matches
    ✅ got: (a)
(b)

  [🧪 test] a datum comment that moves left keeps its internal shape
    [⚙️ assert] the text matches
    ✅ got: (let ((a 1))
  #;(b
      c)
  a)

  [🧪 test] one blank line is the most a body keeps when asked
    [⚙️ assert] the text matches
    ✅ got: (a

 b)

  [🧪 test] strings are never reflowed or respelled
    [⚙️ assert] the text matches
    ✅ got: (display "a   b\n")

  [🧪 test] a project that writes parentheses keeps them
    [⚙️ assert] the text matches
    ✅ got: (cond ((< n 0) 'negative)
      (else 'positive))
+----------------------------------------------+
[📑 suite] gexps
  [🧪 test] a formatted gexp is left alone
    [⚙️ assert] the text matches
    ✅ got: #~(use-modules (guix build utils))

  [🧪 test] `#$@` splices a list
    ✅ got: ((#{#$@}# (list 1)))
  [🧪 test] `#~` is a prefix on the datum it makes
    ✅ got: ((#{#~}# (mkdir output)))
  [🧪 test] a prefix is glued to its datum, and none is followed by a space
    [⚙️ assert] the text matches
    ✅ got: (list #$output #$@(list 1))

  [🧪 test] `#+` stays a conditional in Common Lisp
    ✅ got: ()
  [🧪 test] the body of a gexp is read as code
    [⚙️ assert] the findings are where they should be
    ✅ got: ((1 4))
  [🧪 test] `#+` and `#+@` are gexp prefixes in Scheme
    ✅ got: ((#{#+}# coreutils))
    ✅ got: ((#{#+@}# (list 1)))
  [🧪 test] formatting a gexp is a fixed point
    [⚙️ assert] formatting is a fixed point
    ✅ got: #~(mkdir #$output #$(file-append coreutils "/bin/ls"))

  [🧪 test] `#$` is a prefix, not part of the atom
    ✅ got: ((list (#{#$}# output)))
+----------------------------------------------+
[📑 suite] JSON
  [🧪 test] a trailing comma is refused
    [⚙️ assert] an object with a trailing comma: it is refused
    ✅ got: #t
    [⚙️ assert] an object with a trailing comma: on line 1
    ✅ got: 1
    [⚙️ assert] an object with a trailing comma: at column 8
    ✅ got: 8
  [🧪 test] trailing text after the value is refused
    [⚙️ assert] the document is refused: it is refused
    ✅ got: #t
    [⚙️ assert] the document is refused: on line 1
    ✅ got: 1
    [⚙️ assert] the document is refused: at column 4
    ✅ got: 4
  [🧪 test] whitespace between tokens is not part of the value
    [⚙️ assert] the document is written back the same
    ✅ got: {"a":[1,2]}
  [🧪 test] an object is not an array, and neither is a list
    ✅ got: #t
    ✅ got: #t
    ✅ got: #t
    ✅ got: #t
  [🧪 test] an escaped solidus is a solidus
    [⚙️ assert] the text matches
    ✅ got: a/b
  [🧪 test] an empty object is not an empty array
    [⚙️ assert] the document is written back the same
    ✅ got: {}
    [⚙️ assert] the document is written back the same
    ✅ got: []
  [🧪 test] a bare word is refused
    [⚙️ assert] the document is refused: it is refused
    ✅ got: #t
    [⚙️ assert] the document is refused: on line 1
    ✅ got: 1
    [⚙️ assert] the document is refused: at column 2
    ✅ got: 2
  [🧪 test] a surrogate pair becomes one character
    [⚙️ assert] the text matches
    ✅ got: 😀
  [🧪 test] the position of an error counts lines from one
    [⚙️ assert] the document is refused: it is refused
    ✅ got: #t
    [⚙️ assert] the document is refused: on line 3
    ✅ got: 3
    [⚙️ assert] the document is refused: at column 1
    ✅ got: 1
  [🧪 test] a lone surrogate does not raise
    [⚙️ assert] the text matches
    ✅ got: �x
  [🧪 test] an object keeps the order it was written in
    [⚙️ assert] the document is written back the same
    ✅ got: {"jsonrpc":"2.0","id":1,"method":"initialize"}
  [🧪 test] the escapes JSON requires are read back as characters
    [⚙️ assert] the text matches
    ✅ got: a"b\c
d       e
  [🧪 test] a control character is written as an escape
    [⚙️ assert] the text matches
    ✅ got: "\u0001"
  [🧪 test] an unterminated string is refused
    [⚙️ assert] a malformed member name: it is refused
    ✅ got: #t
    [⚙️ assert] a malformed member name: on line 1
    ✅ got: 1
    [⚙️ assert] a malformed member name: at column 6
    ✅ got: 6
  [🧪 test] a number that is not finite is written as null
    [⚙️ assert] the text matches
    ✅ got: null
  [🧪 test] an array of mixed values round trips
    [⚙️ assert] the document is written back the same
    ✅ got: [1,-2500,true,false,null,"a"]
  [🧪 test] a member is found by its name, or a default is answered
    ✅ got: 1
    ✅ got: missing
    [⚙️ assert] the text matches
    ✅ got: [1,2]
  [🧪 test] a string that needs escaping is written escaped
    [⚙️ assert] the text matches
    ✅ got: "a\"b\\c\nd"
  [🧪 test] a missing comma is refused
    [⚙️ assert] the document is refused: it is refused
    ✅ got: #t
    [⚙️ assert] the document is refused: on line 1
    ✅ got: 1
    [⚙️ assert] the document is refused: at column 4
    ✅ got: 4
  [🧪 test] a symbol names a member as well as a string does
    ✅ got: 1
  [🧪 test] a nested document round trips
    [⚙️ assert] the document is written back the same
    ✅ got: {"params":{"capabilities":{"textDocument":{"formatting":{}}}}}
  [🧪 test] numbers are written the way they are read
    [⚙️ assert] 0 round trips
    ✅ got: 0
    [⚙️ assert] 1 round trips
    ✅ got: 1
    [⚙️ assert] -1 round trips
    ✅ got: -1
    [⚙️ assert] 2500 round trips
    ✅ got: 2500
    [⚙️ assert] -2500 round trips
    ✅ got: -2500
    [⚙️ assert] 1.5 round trips
    ✅ got: 1.5
    [⚙️ assert] 0.25 round trips
    ✅ got: 0.25
  [🧪 test] a \u escape becomes the character it names
    [⚙️ assert] the text matches
    ✅ got: é
+----------------------------------------------+
[📑 suite] language server
  [🧪 test] the dialect follows the language identifier the editor sent
    [⚙️ assert] the rule that only Emacs Lisp has fired
    ✅ got: #t
  [🧪 test] a column is counted in the units the protocol counts
    [⚙️ assert] the trailing whitespace was found
    ✅ got: #t
    [⚙️ assert] the emoji counted as the two units it is
    ✅ got: 13
  [🧪 test] exit without a shutdown ends with the status the protocol asks for
    ✅ got: 1
  [🧪 test] the outline nests a definition inside the one that holds it
    ✅ got: 1
    ✅ got: f
    [⚙️ assert] `g' is inside `f', not beside it
    ✅ got: 1
    ✅ got: g
  [🧪 test] closing a buffer takes its findings away
    [⚙️ assert] the last word about the file is that it has no findings
    ✅ got: 0
  [🧪 test] formatting answers with the text sift would write
    [⚙️ assert] one edit came back
    ✅ got: #t
    [⚙️ assert] the edit is the buffer, indented
    ✅ got:   (if (ready?)
  [🧪 test] the same text is not checked twice
    [⚙️ assert] one buffer, one publication
    ✅ got: 1
  [🧪 test] the dialect layer still answers about a buffer sift cannot finish
    ✅ got: 0
    [⚙️ assert] a code action array came back
    ✅ got: #t
  [🧪 test] an Emacs Lisp defun is a definition
    ✅ got: 0
    [⚙️ assert] `greet' behind the `defun'
    ✅ got: 7
  [🧪 test] the settings are read again when the client says they changed
    ✅ got: 0
    [⚙️ assert] the buffer was checked against the new settings
    ✅ got: 2
    [⚙️ assert] and the editor can see that it happened
    ✅ got: #t
  [🧪 test] a symbol with no definition answers with nothing at all
    [⚙️ assert] `f' is defined, so this is the definition
    ✅ got: 1
    [⚙️ assert] a name nothing defines is an empty answer, not an error
    ✅ got: 0
  [🧪 test] a client that asks for quickfixes gets quickfixes and nothing else
    [⚙️ assert] something was offered
    ✅ got: #t
    [⚙️ assert] no rewrite and no fix-all were mixed in
    ✅ got: (quickfix)
  [🧪 test] a change sent as a range is applied to the text
    ✅ got: 0
    [⚙️ assert] the `if` the range replaced is gone
    ✅ got: ()
  [🧪 test] organizing imports removes the ones nothing uses
    [⚙️ assert] the unused import went, and the file still reads
    ✅ got: (import (scheme base))
(display 1)

  [🧪 test] a symbol jumps to the definition that names it
    [⚙️ assert] one definition, not every `square' in the file
    ✅ got: 1
    ✅ got: 0
    ✅ got: 9
  [🧪 test] a change republishes the findings of the new text
    ✅ got: 0
    [⚙️ assert] the clean text has nothing to report
    ✅ got: 0
  [🧪 test] a reference inside a let jumps to the binding, not the outer name
    [⚙️ assert] the `let' binding, on the second line
    ✅ got: 1
    ✅ got: 9
  [🧪 test] a finding carries the range an editor highlights
    [⚙️ assert] the if is on the second line, counted from zero
    ✅ got: 1
    [⚙️ assert] at the column the `if` itself is in
    ✅ got: 3
  [🧪 test] the server says what it did in the editor's log
    [⚙️ assert] the server logged something
    ✅ got: #t
    [⚙️ assert] as information, not as a complaint
    ✅ got: 3
    [⚙️ assert] and named the findings it published
    ✅ got: #t
  [🧪 test] initialize advertises the navigation requests
    [⚙️ assert] definitions
    ✅ got: true
    [⚙️ assert] references
    ✅ got: true
    [⚙️ assert] highlights
    ✅ got: true
    [⚙️ assert] an outline
    ✅ got: true
    [⚙️ assert] a workspace search
    ✅ got: true
    [⚙️ assert] a rename, with a pre-flight check
    ✅ got: true
  [🧪 test] a Common Lisp defparameter is a definition
    ✅ got: 0
    ✅ got: 14
  [🧪 test] an expression can be extracted to a procedure
    ✅ got: refactor.extract
    [⚙️ assert] the expression is replaced by the call
    ✅ got: (extracted w h)
    [⚙️ assert] and the procedure takes the enclosing parameters
    ✅ got: (define (extracted w h)
  [🧪 test] a keyword argument is not hinted
    [⚙️ assert] only the positional argument is named
    ✅ got: (name  )
  [🧪 test] a notification that raises does not take the server with it
    [⚙️ assert] the editor was told the request was not usable
    ✅ got: #t
    [⚙️ assert] and the next request was answered normally
    ✅ got: null
  [🧪 test] a call sift cannot resolve gets no inlay hint
    [⚙️ assert] an invented name would be worse than none
    ✅ got: 0
  [🧪 test] the highlights mark the declaration apart from the uses
    ✅ got: 2
    [⚙️ assert] the declaration is a write
    ✅ got: 3
    [⚙️ assert] the use is a read
    ✅ got: 2
  [🧪 test] formatting a buffer that does not parse says why instead of nothing
    ✅ got: 0
    [⚙️ assert] no edit is offered, because sift does not guess
    ✅ got: 0
    [⚙️ assert] the editor is told that formatting was refused
    ✅ got: #t
    [⚙️ assert] as an error
    ✅ got: 1
    ✅ got: cannot format
  [🧪 test] an unknown method is refused and the server keeps its answers
    ✅ got: -32601
    [⚙️ assert] shutdown and exit end the server with 0
    ✅ got: 0
  [🧪 test] a file changed on disk is a reason to check the open buffers
    ✅ got: 0
    [⚙️ assert] the open buffer is still answered for
    ✅ got: #t
  [🧪 test] a definition in another buffer is found
    ✅ got: 1
    [⚙️ assert] the jump leaves the buffer it started in
    ✅ got: file:///tmp/sift-lsp-test-lib.scm
    ✅ got: 9
  [🧪 test] a setting the client sends that sift does not have is reported
    [⚙️ assert] the editor can see that the setting went nowhere
    ✅ got: #t
  [🧪 test] an inlay hint sits where its argument starts
    [⚙️ assert] on the line of the call, counted from zero
    ✅ got: 3
    ✅ got: name  
  [🧪 test] the project chooses which kinds of hint it gets
    [⚙️ assert] types alone means no parameter names
    ✅ got: (1)
  [🧪 test] an unknown request is refused, and the server keeps talking
    [⚙️ assert] the method is not implemented
    ✅ got: -32601
    [⚙️ assert] the next request was still answered
    ✅ got: #t
  [🧪 test] a buffer that does not parse has findings, not silence
    ✅ got: 0
    [⚙️ assert] the file that never closes is reported as an error
    ✅ got: #t
    [⚙️ assert] and the finding is named, not anonymous
    ✅ got: #t
  [🧪 test] the hover describes the symbol rather than the line
    ✅ got: **square**
    ✅ got: function
    [⚙️ assert] the definition's own docstring, not the rule's
    ✅ got: Square X.
  [🧪 test] the editor's settings are part of the configuration
    [⚙️ assert] a setting the server does not have a file for is not a failure
    ✅ got: 0
    [⚙️ assert] and turning the hints off turns them off
    ✅ got: 0
  [🧪 test] a code action offers the rule's own fix
    [⚙️ assert] an action was offered
    ✅ got: #t
    ✅ got: quickfix
    ✅ got: SIFT012
    [⚙️ assert] the fix is the one that turns if into when
    ✅ got: when
  [🧪 test] a parameter list is not a call to the procedure it defines
    ✅ got: 0
  [🧪 test] one action fixes every safe finding in the buffer
    [⚙️ assert] one action, not one per finding
    ✅ got: 1
    ✅ got: source.fixAll.sift
    [⚙️ assert] the `if' was rewritten
    ✅ got: when
    [⚙️ assert] and the trailing whitespace went with it
    ✅ got: #f
  [🧪 test] new text is checked again even when its findings look the same
    [⚙️ assert] the new text was reported
    ✅ got: 2
    [⚙️ assert] and the finding moved with the text around it
    ✅ got: 2
  [🧪 test] an import that is already organized has no action
    [⚙️ assert] nothing to offer, and nothing offered
    ✅ got: 0
  [🧪 test] prepareRename says what would be renamed, and rename edits every mention
    ✅ got: f
    ✅ got: 1
    [⚙️ assert] the definition and the call
    ✅ got: 2
    ✅ got: g
    [⚙️ assert] the edit is pinned to the version it was computed from
    ✅ got: 1
  [🧪 test] a save asks the server to look at the buffer again
    ✅ got: 0
    [⚙️ assert] the buffer is reported, and reported again after the save
    ✅ got: 2
  [🧪 test] signature help says nothing about a call sift cannot see
    [⚙️ assert] no invented signature
    ✅ got: null
  [🧪 test] organizing imports puts the specs in order
    ✅ got: source.organizeImports
    [⚙️ assert] the library that sorts first is written first
    ✅ got: (import (scheme base) (srfi 1))
(display 1)

  [🧪 test] the definition under the cursor can be reformatted on its own
    ✅ got: refactor.rewrite
    [⚙️ assert] the body was indented
    ✅ got:   (* x x))
    [⚙️ assert] the edit starts at the definition
    ✅ got: 0
    [⚙️ assert] and ends with it, leaving the next definition alone
    ✅ got: 1
  [🧪 test] inlay hints name the positional arguments of a call
    ✅ got: 0
    [⚙️ assert] one hint per argument, named by the definition
    ✅ got: (parent   width   height   title  )
    [⚙️ assert] and each one is a parameter, which is how an editor styles it
    ✅ got: 2
  [🧪 test] a literal's type is hinted when the project asks for it
    [⚙️ assert] the parameters are named, as before
    ✅ got: (parent   width   title  )
    [⚙️ assert] and a literal says its own type
    ✅ got: (number   string  )
  [🧪 test] a name says nothing about its type
    [⚙️ assert] only the argument whose type is written down
    ✅ got: (number  )
  [🧪 test] a request before initialize is refused by the protocol's rule
    [⚙️ assert] the server says it has not been initialized
    ✅ got: -32002
  [🧪 test] a client that asks for quickfixes gets no extraction
    [⚙️ assert] no extraction was mixed in
    ✅ got: #f
  [🧪 test] a rename that is not a symbol name is refused, not written
    ✅ got: -32602
  [🧪 test] opening a buffer publishes its findings
    ✅ got: 0
    [⚙️ assert] the if has no else branch
    ✅ got: #t
    [⚙️ assert] a warning is a warning
    ✅ got: 2
  [🧪 test] a setting the client sends with initialize is the configuration too
    [⚙️ assert] the session started with the editor's settings
    ✅ got: 0
  [🧪 test] the hover says what the rule wants
    ✅ got: SIFT012
    ✅ got: if-without-else
  [🧪 test] a configuration the server was started with is what it answers with
    [⚙️ assert] a warning is below the severity the server was given
    ✅ got: 0
  [🧪 test] a message that is not JSON is answered, and the session goes on
    [⚙️ assert] the server exited cleanly
    ✅ got: 0
    [⚙️ assert] initialize was answered
    ✅ got: #t
    [⚙️ assert] the request after the bad message was answered too
    ✅ got: #t
  [🧪 test] signature help answers with the definition's own formal list
    ✅ got: (greet name)
    [⚙️ assert] the cursor is in the first argument
    ✅ got: 0
    [⚙️ assert] the docstring comes with it
    ✅ got: Greet NAME.
  [🧪 test] completion puts the name being typed first
    [⚙️ assert] the prefix match is offered first
    ✅ got: alpha-one
    [⚙️ assert] and its sort text says why
    ✅ got: alpha-one
  [🧪 test] the name of a parameter is its own definition
    [⚙️ assert] a request on the binding answers with the binding
    ✅ got: 1
    ✅ got: 11
  [🧪 test] a client with no language for the file still gets its findings
    ✅ got: 0
    [⚙️ assert] the finding was published from the file's own extension
    ✅ got: #t
    [⚙️ assert] and nothing was wrong enough to interrupt anybody
    ✅ got: #t
  [🧪 test] signature help counts the arguments already written
    [⚙️ assert] one argument is finished, so the second is being written
    ✅ got: 1
  [🧪 test] initialize names the capabilities sift offers
    ✅ got: 0
    [⚙️ assert] a change replaces the whole buffer
    ✅ got: 1
    [⚙️ assert] the server hears about a buffer opening and closing
    ✅ got: true
    [⚙️ assert] and about a save, which is what refreshes the project
    ✅ got: #t
    [⚙️ assert] the server formats
    ✅ got: true
    [⚙️ assert] the server offers fixes, extractions, the one rewrite it can make, and import sorting
    ✅ got: #(quickfix refactor.extract refactor.rewrite source.fixAll source.fixAll.sift source.organizeImports)
    [⚙️ assert] the server answers a hover
    ✅ got: true
  [🧪 test] a jump is answered from the project when the client names a root
    ✅ got: 0
    [⚙️ assert] the file that defines the name was found
    ✅ got: #t
    [⚙️ assert] and it is the file on disk, not a buffer
    ✅ got: file:///tmp/sift-test-31218-266/other.scm
    ✅ got: 0
  [🧪 test] completion offers the names the project defines
    [⚙️ assert] from this buffer
    ✅ got: #t
    [⚙️ assert] from the one next to it
    ✅ got: #t
  [🧪 test] an expression can be extracted to a let binding
    [⚙️ assert] an extraction was offered
    ✅ got: #t
    ✅ got: refactor.extract
    [⚙️ assert] the expression was hoisted into a binding
    ✅ got: (let ((value (* w h))) (+ value 1))
  [🧪 test] shutdown is answered and exit ends the session
    ✅ got: 0
    ✅ got: null
  [🧪 test] references list every mention in the project
    [⚙️ assert] the definition and the use
    ✅ got: 2
    [⚙️ assert] this buffer's mention first, then the other one's
    ✅ got: (file:///tmp/sift-lsp-test.scm file:///tmp/sift-lsp-test-lib.scm)
  [🧪 test] workspace/symbol searches the buffers the editor has open
    ✅ got: 1
    ✅ got: square
+----------------------------------------------+
[📑 suite] pool: many files, one order
  [🧪 test] an error reaches the caller instead of vanishing in a thread
    [⚙️ assert] the caller sees the error the work raised
    ✅ success catching error: misc-error: (#f no ~S (5) #f)
  [🧪 test] the error is the one the work raised, not a summary of it
    [⚙️ assert] the key and its arguments arrive unchanged
    ✅ got: (0 1 2)
  [🧪 test] one worker answers what many workers answer
    [⚙️ assert] the same answers, however they were spread
    ✅ got: (0 0 1 3 6 10 15 21 21 22 24 27 31 36 42 42 43 45 48 52 57 63 63 64 66 69 73 78 84 84 85 87 90 94 99 105 105 106 108 111)
  [🧪 test] the empty list is answered without a thread
    ✅ got: ()
  [🧪 test] the answers are in the order the work was given
    [⚙️ assert] the order is the order of the items
    ✅ got: (0 1 4 9 16 25 36 49)
+----------------------------------------------+
[📑 suite] reader: Common Lisp
  [🧪 test] a keyword is an atom of its own kind
    ✅ got: (keyword)
  [🧪 test] no parse error is reported for Common Lisp syntax
    ✅ got: ()
  [🧪 test] a pathname is a prefix over a string
    [⚙️ assert] the text matches
    ✅ got: (probe-file #p"/tmp/x")
  [🧪 test] block comments nest
    [⚙️ assert] the text matches
    ✅ got: #| a #| b |# c |# x
  [🧪 test] a read macro keeps its datum glued to it
    [⚙️ assert] the text matches
    ✅ got: #2A((1 2) (3 4))
    [⚙️ assert] the text matches
    ✅ got: #c(1 2)
    [⚙️ assert] the text matches
    ✅ got: #1=(a . #1#)
    [⚙️ assert] the text matches
    ✅ got: #*1011
  [🧪 test] radix and exactness prefixes are kept
    [⚙️ assert] the text matches
    ✅ got: (list #x1F #o17 #b1010 #e1.0)
  [🧪 test] a structure literal is a prefix over a list
    [⚙️ assert] the text matches
    ✅ got: #s(point :x 1 :y 2)
  [🧪 test] a bracket and a hash are symbol characters here
    ✅ got: (A[B A#B)
    [⚙️ assert] the text matches
    ✅ got: (defun f () A[B)
  [🧪 test] a LOOP form is read as ordinary forms
    [⚙️ assert] the text matches
    ✅ got: (loop :for x :in xs :do (print x))
  [🧪 test] a datum comment is Scheme syntax, and is reported here
    ✅ got: ((1 1 the))
  [🧪 test] a Common Lisp file round-trips byte for byte
    [⚙️ assert] the text matches
    ✅ got: (defpackage :demo (:use :cl) (:export #:run))

(in-package :demo)

(defun run ()
  "Run it."
  (format t "~a~%" 1))

  [🧪 test] a feature conditional keeps both halves
    ✅ got: ((feature sbcl) (form (defun f ())))
  [🧪 test] a feature expression may be a list
    [⚙️ assert] the text matches
    ✅ got: #+(or sbcl ccl) (defun f ())
  [🧪 test] a negated feature conditional is kept
    [⚙️ assert] the text matches
    ✅ got: #-(not sbcl) (defun f ())
  [🧪 test] an unreadable object is copied verbatim
    [⚙️ assert] the text matches
    ✅ got: #<buffer foo>
    [⚙️ assert] the text matches
    ✅ got: (describe #<window 1 on foo>)
  [🧪 test] package markers are kept apart
    ✅ got: ((foo:bar . foo:) (foo::baz . foo::) (:key . #f) (#:uninterned . #:))
  [🧪 test] read-time evaluation is copied and not evaluated
    [⚙️ assert] the text matches
    ✅ got: #.(+ 1 2)
    ✅ got: (#.(+ 1 2))
  [🧪 test] a pathname keeps the case of its dispatch character
    [⚙️ assert] the text matches
    ✅ got: (probe-file #P"/tmp/x")
    ✅ got: ()
  [🧪 test] a quote ends a symbol here
    ✅ got: (a)
  [🧪 test] a case-sensitive symbol keeps its case
    [⚙️ assert] the text matches
    ✅ got: (defun make-Thing () (list :Thing))
  [🧪 test] a datum comment holds one datum
    [⚙️ assert] the text matches
    ✅ got: #;foo bar
+----------------------------------------------+
[📑 suite] reader: Emacs Lisp
  [🧪 test] a character literal with a meta and a control modifier is one atom
    ✅ got: (?\M-\C-x)
  [🧪 test] a brace is a symbol character, not a bracket
    ✅ got: ({ _ })
  [🧪 test] a read-circle label is a prefix over its datum
    [⚙️ assert] the text matches
    ✅ got: #1=(a . #1#)
  [🧪 test] vectors are read as vectors
    ✅ got: (#(1 2 3))
  [🧪 test] a dotted pair keeps its dot
    [⚙️ assert] the text matches
    ✅ got: (a . b)
  [🧪 test] a function quote is a prefix, like a quote
    ✅ got: ((function foo) (quote bar))
  [🧪 test] an Emacs Lisp file round-trips byte for byte
    [⚙️ assert] the text matches
    ✅ got: ;;; demo.el --- a demo -*- lexical-binding: t; -*-

(defun demo (x)
  "Return X."
  (message "%s" x))

(provide 'demo)

  [🧪 test] a bar is an ordinary symbol character, not an escape
    ✅ got: ()
    ✅ got: (| a b)
  [🧪 test] a hash-table literal is a read macro over a list
    [⚙️ assert] the text matches
    ✅ got: (defvar t #s(hash-table test equal data ("a" 1)))
  [🧪 test] the dialect is detected from a lexical-binding marker
    ✅ got: elisp
  [🧪 test] a backslash quotes the next character of a symbol
    ✅ got: ()
    ✅ got: (\( \) a\#b)
  [🧪 test] character literals keep their spelling
    ✅ got: (?a ?\n ?\C-x ?\M-x ?\s ?\()
  [🧪 test] a Scheme character literal is reported, and still kept
    ✅ got: ((1 1 character))
    [⚙️ assert] the text matches
    ✅ got: #\a
  [🧪 test] a defun keeps its name, argument list, docstring and body
    ✅ got: ((defun add (a b) "Add A and B." (+ a b)))
  [🧪 test] docstrings with escapes are not respelled
    [⚙️ assert] the text matches
    ✅ got: (defun f ()
  "Say \"hi\"."
  nil)
  [🧪 test] a datum comment is reported, and still kept
    ✅ got: ((1 1 the))
    [⚙️ assert] the text matches
    ✅ got: #;foo bar
  [🧪 test] the lexical-binding header is an ordinary comment
    [⚙️ assert] the text matches
    ✅ got: ;;; foo.el --- a package -*- lexical-binding: t; -*-

  [🧪 test] the dialect is detected from the extension
    ✅ got: elisp
  [🧪 test] a shebang line is kept
    [⚙️ assert] the text matches
    ✅ got: #!/usr/bin/env emacs --script
(message "hi")

  [🧪 test] a block comment is reported, and still kept
    ✅ got: ((1 1 block))
    [⚙️ assert] the text matches
    ✅ got: #| not elisp |# x
+----------------------------------------------+
[📑 suite] reader: Scheme
  [🧪 test] locations count characters, not bytes
    ✅ got: 1
    ✅ got: 4
    ✅ got: 4
  [🧪 test] a quote or a comma inside a symbol belongs to it
    ✅ got: (define x' 1)
    ✅ got: (list lst'' a,b)
    [⚙️ assert] the text matches
    ✅ got: (define x' 1)
  [🧪 test] extended symbols are Guile syntax, and say so elsewhere
    ✅ got: ((1 1 extended))
  [🧪 test] a vector node knows it is a vector, and a bracket is one only in Elisp
    [⚙️ assert] a `#(' literal
    ✅ got: #t
    ✅ got: #(
    [⚙️ assert] a Scheme clause written with a bracket
    ✅ got: #f
    [⚙️ assert] an Emacs Lisp vector
    ✅ got: #t
  [🧪 test] a whole file of trivia round-trips byte for byte
    [⚙️ assert] the text matches
    ✅ got: ;; a comment

;; another

  [🧪 test] a backslash-newline inside a string is kept
    [⚙️ assert] the text matches
    ✅ got: "one \
two"
  [🧪 test] read-time evaluation is Common Lisp syntax, and is reported
    ✅ got: ((1 1 read-time))
    [⚙️ assert] the text matches
    ✅ got: #.(+ 1 2)
  [🧪 test] block comments nest, and none of them is lost
    [⚙️ assert] the text matches
    ✅ got: #| a #| b |# c |# x
  [🧪 test] a list is a list of its elements
    ✅ got: ((a b (c d)))
  [🧪 test] a Guile extended symbol is one atom, spaces and all
    ✅ got: ()
    ✅ got: symbol
    ✅ got: #{foo bar}#
  [🧪 test] numbers are not normalised
    ✅ got: (16 5 1 1/3 1.0e10)
  [🧪 test] CRLF is read as one newline per line
    [⚙️ assert] the text matches
    ✅ got: (a
 b)

  [🧪 test] a read macro over a glued datum is one node
    ✅ got: ()
    ✅ got: prefix
    ✅ got: #1=
    [⚙️ assert] the text matches
    ✅ got: #S(point :x 1)
  [🧪 test] the reader marks everything inside a datum comment
    [⚙️ assert] the datum itself
    ✅ got: #t
    [⚙️ assert] its children
    ✅ got: #t
  [🧪 test] a Chez directive inside a form is an atom
    ✅ got: ()
    [⚙️ assert] the text matches
    ✅ got: (lambda (x #!optional y) x)
  [🧪 test] an extended symbol round-trips, newline and escape included
    [⚙️ assert] the text matches
    ✅ got: (define #{what
ever}# 1)

    [⚙️ assert] the text matches
    ✅ got: '#{a\}b}#
  [🧪 test] a brace is a symbol character, not a bracket
    ✅ got: ()
    ✅ got: ({a b})
    [⚙️ assert] the text matches
    ✅ got: {a
b}
  [🧪 test] every reader prefix applies to one datum
    ✅ got: ((quote a) (quasiquote (b (unquote c) (unquote-splicing d))) (function e))
  [🧪 test] an unterminated form is reported at its opener
    ✅ got: ((1 1 unterminated))
    ✅ got: ((a (b c)))
  [🧪 test] both spellings of a bytevector are the same datum
    [⚙️ assert] the text matches
    ✅ got: (vector-ref #vu8(1 2) 0)
    [⚙️ assert] `#vu8(' is a bytevector
    ✅ got: #t
  [🧪 test] a block comment between two elements is preserved
    [⚙️ assert] the text matches
    ✅ got: (a #| note |# b)
  [🧪 test] a datum comment holds exactly one datum
    ✅ got: (a b)
    [⚙️ assert] the text matches
    ✅ got: #;foo a
  [🧪 test] a file that is already formatted round-trips byte for byte
    [⚙️ assert] the text matches
    ✅ got: (define (square x)
  (* x x))

;; done

  [🧪 test] a reader directive is a token, not a shebang
    ✅ got: ()
    ✅ got: atom
    ✅ got: #!r6rs
    [⚙️ assert] the text matches
    ✅ got: #!fold-case
(a)

  [🧪 test] an inline comment knows it follows code
    ✅ got: (#f #t)
  [🧪 test] an unterminated extended symbol is reported at its opener
    ✅ got: ((1 1 unterminated))
  [🧪 test] an unterminated string is reported at its quote
    ✅ got: ((1 4 unterminated) (1 1 unterminated))
  [🧪 test] character literals keep their spelling
    ✅ got: (#\a #\space #\newline #\x41)
  [🧪 test] a shebang names which Scheme is running the file
    ✅ got: scheme
    ✅ got: scheme
    ✅ got: scheme
  [🧪 test] an extended symbol is a symbol even when it looks like a number
    ✅ got: (#{}# #{4242}#)
    ✅ got: (symbol symbol)
  [🧪 test] the datum comment may hold a datum with a datum comment
    [⚙️ assert] the text matches
    ✅ got: #;#;a b c
  [🧪 test] string escapes are kept exactly as they were written
    [⚙️ assert] the text matches
    ✅ got: (display "a \" b\n\t\x41;")
  [🧪 test] a dotted pair keeps its dot as an atom
    [⚙️ assert] the text matches
    ✅ got: (a . b)
    ✅ got: (a . b)
  [🧪 test] a datum comment inside a list comments out one element
    ✅ got: ((a c))
  [🧪 test] comments are kept, every one of them
    ✅ got: (;; one ;; two ; not three ;; three)
  [🧪 test] nested prefixes stay on the datum they belong to
    ✅ got: ((quote #(1 2)))
    ✅ got: ((quote (quasiquote (a (unquote b)))))
  [🧪 test] a syntax-case prefix is a prefix, and its datum is glued to it
    ✅ got: ()
    ✅ got: #`
    ✅ got: a
    ✅ got: #,
    ✅ got: #,@
    [⚙️ assert] the text matches
    ✅ got: (display #`(a #,b #,@c))
  [🧪 test] blank lines are nodes, so they survive a round trip
    [⚙️ assert] the text matches
    ✅ got: (a)


(b)

  [🧪 test] a vector keeps the comments written inside it
    [⚙️ assert] the text matches
    ✅ got: #(a #| note |# b)
  [🧪 test] a prefix separated from its datum still reads
    ✅ got: ((quote a))
  [🧪 test] top-level atoms keep their kind
    ✅ got: (symbol keyword number number string character)
  [🧪 test] vectors and bytevectors are read with their own opener
    ✅ got: (#(1 2 3))
    ✅ got: #u8(1 2)
  [🧪 test] a shebang is a node, not a reader directive
    [⚙️ assert] the text matches
    ✅ got: #!/usr/bin/env guile
(foo)

  [🧪 test] an unmatched closer is reported, and the rest of the file is read
    ✅ got: ((1 2 unmatched))
    ✅ got: (a ) b)
+----------------------------------------------+
[📑 suite] robustness
  [🧪 test] an empty body is reported rather than raising
    ✅ got: 1
  [🧪 test] formatting an odd source twice changes nothing
    [⚙️ assert] idempotent: ""
    ✅ got: 
    [⚙️ assert] idempotent: " "
    ✅ got: 
    [⚙️ assert] idempotent: "\n\n\n"
    ✅ got: 
    [⚙️ assert] idempotent: "("
    ✅ got: (
    [⚙️ assert] idempotent: ")"
    ✅ got: )
    [⚙️ assert] idempotent: "())"
    ✅ got: ())
    [⚙️ assert] idempotent: "(defun)"
    ✅ got: (defun)
    [⚙️ assert] idempotent: "(defun defmacro)"
    ✅ got: (defun defmacro)
    [⚙️ assert] idempotent: "(defun f)"
    ✅ got: (defun f)
    [⚙️ assert] idempotent: "(defun f ()"
    ✅ got: (defun f ()
    [⚙️ assert] idempotent: "(defmacro)"
    ✅ got: (defmacro)
    [⚙️ assert] idempotent: "(let)"
    ✅ got: (let)
    [⚙️ assert] idempotent: "(let ())"
    ✅ got: (let ())
    [⚙️ assert] idempotent: "(case)"
    ✅ got: (case)
    [⚙️ assert] idempotent: "(case x)"
    ✅ got: (case x)
    [⚙️ assert] idempotent: "(case x ())"
    ✅ got: (case x [])
    [⚙️ assert] idempotent: "(case x ((cond) 1))"
    ✅ got: (case x [(cond) 1])
    [⚙️ assert] idempotent: "(cond)"
    ✅ got: (cond)
    [⚙️ assert] idempotent: "(cond ())"
    ✅ got: (cond [])
    [⚙️ assert] idempotent: "(lambda)"
    ✅ got: (lambda)
    [⚙️ assert] idempotent: "(lambda ())"
    ✅ got: (lambda ())
    [⚙️ assert] idempotent: "(define)"
    ✅ got: (define)
    [⚙️ assert] idempotent: "(define ())"
    ✅ got: (define ())
    [⚙️ assert] idempotent: "(quote)"
    ✅ got: (quote)
    [⚙️ assert] idempotent: "'"
    ✅ got: '
    [⚙️ assert] idempotent: "#"
    ✅ got: #
    [⚙️ assert] idempotent: "#;"
    ✅ got: #;
    [⚙️ assert] idempotent: "#|"
    ✅ got: #|
    [⚙️ assert] idempotent: "#\\"
    ✅ got: #\
    [⚙️ assert] idempotent: "?\\"
    ✅ got: ?\
    [⚙️ assert] idempotent: "(a . )"
    ✅ got: (a .)
    [⚙️ assert] idempotent: "(a . b . c)"
    ✅ got: (a . b . c)
    [⚙️ assert] idempotent: "(#)"
    ✅ got: (#)
    [⚙️ assert] idempotent: "(list #;)"
    ✅ got: (list #;)
    [⚙️ assert] idempotent: "(list #|x|#)"
    ✅ got: (list #|x|#)
    [⚙️ assert] idempotent: "(((("
    ✅ got: ((((
    [⚙️ assert] idempotent: "))))"
    ✅ got: ))))
    [⚙️ assert] idempotent: "(f :a 1 :a 2)"
    ✅ got: (f :a 1 :a 2)
    [⚙️ assert] idempotent: "(f \"unterminated"
    ✅ got: (f "unterminated
    [⚙️ assert] idempotent: "(f #<garbage)"
    ✅ got: (f #<garbage)
    [⚙️ assert] idempotent: "(f #.(+ 1 2))"
    ✅ got: (f #.(+ 1 2))
    [⚙️ assert] idempotent: "(let ((x 1) (x 2)) x)"
    ✅ got: (let ((x 1) (x 2)) x)
    [⚙️ assert] idempotent: "(when)"
    ✅ got: (when)
    [⚙️ assert] idempotent: "(unless)"
    ✅ got: (unless)
    [⚙️ assert] idempotent: "(if)"
    ✅ got: (if)
    [⚙️ assert] idempotent: "(do)"
    ✅ got: (do)
    [⚙️ assert] idempotent: "(λ (x) x)"
    ✅ got: (λ (x) x)
  [🧪 test] a case clause whose datum is a list of symbols is not a form
    ✅ got: ()
  [🧪 test] every odd source is read, linted and formatted without raising
    [⚙️ assert] scheme: ""
    ✅ got: #t
    [⚙️ assert] scheme: ""
    ✅ got: #t
    [⚙️ assert] scheme: ""
    ✅ got: #t
    [⚙️ assert] scheme: " "
    ✅ got: #t
    [⚙️ assert] scheme: " "
    ✅ got: #t
    [⚙️ assert] scheme: " "
    ✅ got: #t
    [⚙️ assert] scheme: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] scheme: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] scheme: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] scheme: "("
    ✅ got: #t
    [⚙️ assert] scheme: "("
    ✅ got: #t
    [⚙️ assert] scheme: "("
    ✅ got: #t
    [⚙️ assert] scheme: ")"
    ✅ got: #t
    [⚙️ assert] scheme: ")"
    ✅ got: #t
    [⚙️ assert] scheme: ")"
    ✅ got: #t
    [⚙️ assert] scheme: "())"
    ✅ got: #t
    [⚙️ assert] scheme: "())"
    ✅ got: #t
    [⚙️ assert] scheme: "())"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun f)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun f)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun f)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] scheme: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] scheme: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] scheme: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] scheme: "(let)"
    ✅ got: #t
    [⚙️ assert] scheme: "(let)"
    ✅ got: #t
    [⚙️ assert] scheme: "(let)"
    ✅ got: #t
    [⚙️ assert] scheme: "(let ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(let ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(let ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(case)"
    ✅ got: #t
    [⚙️ assert] scheme: "(case)"
    ✅ got: #t
    [⚙️ assert] scheme: "(case)"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] scheme: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] scheme: "(cond)"
    ✅ got: #t
    [⚙️ assert] scheme: "(cond)"
    ✅ got: #t
    [⚙️ assert] scheme: "(cond)"
    ✅ got: #t
    [⚙️ assert] scheme: "(cond ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(cond ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(cond ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(lambda)"
    ✅ got: #t
    [⚙️ assert] scheme: "(lambda)"
    ✅ got: #t
    [⚙️ assert] scheme: "(lambda)"
    ✅ got: #t
    [⚙️ assert] scheme: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(define)"
    ✅ got: #t
    [⚙️ assert] scheme: "(define)"
    ✅ got: #t
    [⚙️ assert] scheme: "(define)"
    ✅ got: #t
    [⚙️ assert] scheme: "(define ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(define ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(define ())"
    ✅ got: #t
    [⚙️ assert] scheme: "(quote)"
    ✅ got: #t
    [⚙️ assert] scheme: "(quote)"
    ✅ got: #t
    [⚙️ assert] scheme: "(quote)"
    ✅ got: #t
    [⚙️ assert] scheme: "'"
    ✅ got: #t
    [⚙️ assert] scheme: "'"
    ✅ got: #t
    [⚙️ assert] scheme: "'"
    ✅ got: #t
    [⚙️ assert] scheme: "#"
    ✅ got: #t
    [⚙️ assert] scheme: "#"
    ✅ got: #t
    [⚙️ assert] scheme: "#"
    ✅ got: #t
    [⚙️ assert] scheme: "#;"
    ✅ got: #t
    [⚙️ assert] scheme: "#;"
    ✅ got: #t
    [⚙️ assert] scheme: "#;"
    ✅ got: #t
    [⚙️ assert] scheme: "#|"
    ✅ got: #t
    [⚙️ assert] scheme: "#|"
    ✅ got: #t
    [⚙️ assert] scheme: "#|"
    ✅ got: #t
    [⚙️ assert] scheme: "#\\"
    ✅ got: #t
    [⚙️ assert] scheme: "#\\"
    ✅ got: #t
    [⚙️ assert] scheme: "#\\"
    ✅ got: #t
    [⚙️ assert] scheme: "?\\"
    ✅ got: #t
    [⚙️ assert] scheme: "?\\"
    ✅ got: #t
    [⚙️ assert] scheme: "?\\"
    ✅ got: #t
    [⚙️ assert] scheme: "(a . )"
    ✅ got: #t
    [⚙️ assert] scheme: "(a . )"
    ✅ got: #t
    [⚙️ assert] scheme: "(a . )"
    ✅ got: #t
    [⚙️ assert] scheme: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] scheme: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] scheme: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] scheme: "(#)"
    ✅ got: #t
    [⚙️ assert] scheme: "(#)"
    ✅ got: #t
    [⚙️ assert] scheme: "(#)"
    ✅ got: #t
    [⚙️ assert] scheme: "(list #;)"
    ✅ got: #t
    [⚙️ assert] scheme: "(list #;)"
    ✅ got: #t
    [⚙️ assert] scheme: "(list #;)"
    ✅ got: #t
    [⚙️ assert] scheme: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] scheme: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] scheme: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] scheme: "(((("
    ✅ got: #t
    [⚙️ assert] scheme: "(((("
    ✅ got: #t
    [⚙️ assert] scheme: "(((("
    ✅ got: #t
    [⚙️ assert] scheme: "))))"
    ✅ got: #t
    [⚙️ assert] scheme: "))))"
    ✅ got: #t
    [⚙️ assert] scheme: "))))"
    ✅ got: #t
    [⚙️ assert] scheme: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] scheme: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] scheme: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] scheme: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] scheme: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] scheme: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] scheme: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] scheme: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] scheme: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] scheme: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] scheme: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] scheme: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] scheme: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(when)"
    ✅ got: #t
    [⚙️ assert] scheme: "(when)"
    ✅ got: #t
    [⚙️ assert] scheme: "(when)"
    ✅ got: #t
    [⚙️ assert] scheme: "(unless)"
    ✅ got: #t
    [⚙️ assert] scheme: "(unless)"
    ✅ got: #t
    [⚙️ assert] scheme: "(unless)"
    ✅ got: #t
    [⚙️ assert] scheme: "(if)"
    ✅ got: #t
    [⚙️ assert] scheme: "(if)"
    ✅ got: #t
    [⚙️ assert] scheme: "(if)"
    ✅ got: #t
    [⚙️ assert] scheme: "(do)"
    ✅ got: #t
    [⚙️ assert] scheme: "(do)"
    ✅ got: #t
    [⚙️ assert] scheme: "(do)"
    ✅ got: #t
    [⚙️ assert] scheme: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] scheme: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] elisp: ""
    ✅ got: #t
    [⚙️ assert] elisp: ""
    ✅ got: #t
    [⚙️ assert] elisp: ""
    ✅ got: #t
    [⚙️ assert] elisp: " "
    ✅ got: #t
    [⚙️ assert] elisp: " "
    ✅ got: #t
    [⚙️ assert] elisp: " "
    ✅ got: #t
    [⚙️ assert] elisp: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] elisp: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] elisp: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] elisp: "("
    ✅ got: #t
    [⚙️ assert] elisp: "("
    ✅ got: #t
    [⚙️ assert] elisp: "("
    ✅ got: #t
    [⚙️ assert] elisp: ")"
    ✅ got: #t
    [⚙️ assert] elisp: ")"
    ✅ got: #t
    [⚙️ assert] elisp: ")"
    ✅ got: #t
    [⚙️ assert] elisp: "())"
    ✅ got: #t
    [⚙️ assert] elisp: "())"
    ✅ got: #t
    [⚙️ assert] elisp: "())"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun f)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun f)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun f)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] elisp: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] elisp: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] elisp: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] elisp: "(let)"
    ✅ got: #t
    [⚙️ assert] elisp: "(let)"
    ✅ got: #t
    [⚙️ assert] elisp: "(let)"
    ✅ got: #t
    [⚙️ assert] elisp: "(let ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(let ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(let ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(case)"
    ✅ got: #t
    [⚙️ assert] elisp: "(case)"
    ✅ got: #t
    [⚙️ assert] elisp: "(case)"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] elisp: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] elisp: "(cond)"
    ✅ got: #t
    [⚙️ assert] elisp: "(cond)"
    ✅ got: #t
    [⚙️ assert] elisp: "(cond)"
    ✅ got: #t
    [⚙️ assert] elisp: "(cond ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(cond ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(cond ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(lambda)"
    ✅ got: #t
    [⚙️ assert] elisp: "(lambda)"
    ✅ got: #t
    [⚙️ assert] elisp: "(lambda)"
    ✅ got: #t
    [⚙️ assert] elisp: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(define)"
    ✅ got: #t
    [⚙️ assert] elisp: "(define)"
    ✅ got: #t
    [⚙️ assert] elisp: "(define)"
    ✅ got: #t
    [⚙️ assert] elisp: "(define ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(define ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(define ())"
    ✅ got: #t
    [⚙️ assert] elisp: "(quote)"
    ✅ got: #t
    [⚙️ assert] elisp: "(quote)"
    ✅ got: #t
    [⚙️ assert] elisp: "(quote)"
    ✅ got: #t
    [⚙️ assert] elisp: "'"
    ✅ got: #t
    [⚙️ assert] elisp: "'"
    ✅ got: #t
    [⚙️ assert] elisp: "'"
    ✅ got: #t
    [⚙️ assert] elisp: "#"
    ✅ got: #t
    [⚙️ assert] elisp: "#"
    ✅ got: #t
    [⚙️ assert] elisp: "#"
    ✅ got: #t
    [⚙️ assert] elisp: "#;"
    ✅ got: #t
    [⚙️ assert] elisp: "#;"
    ✅ got: #t
    [⚙️ assert] elisp: "#;"
    ✅ got: #t
    [⚙️ assert] elisp: "#|"
    ✅ got: #t
    [⚙️ assert] elisp: "#|"
    ✅ got: #t
    [⚙️ assert] elisp: "#|"
    ✅ got: #t
    [⚙️ assert] elisp: "#\\"
    ✅ got: #t
    [⚙️ assert] elisp: "#\\"
    ✅ got: #t
    [⚙️ assert] elisp: "#\\"
    ✅ got: #t
    [⚙️ assert] elisp: "?\\"
    ✅ got: #t
    [⚙️ assert] elisp: "?\\"
    ✅ got: #t
    [⚙️ assert] elisp: "?\\"
    ✅ got: #t
    [⚙️ assert] elisp: "(a . )"
    ✅ got: #t
    [⚙️ assert] elisp: "(a . )"
    ✅ got: #t
    [⚙️ assert] elisp: "(a . )"
    ✅ got: #t
    [⚙️ assert] elisp: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] elisp: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] elisp: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] elisp: "(#)"
    ✅ got: #t
    [⚙️ assert] elisp: "(#)"
    ✅ got: #t
    [⚙️ assert] elisp: "(#)"
    ✅ got: #t
    [⚙️ assert] elisp: "(list #;)"
    ✅ got: #t
    [⚙️ assert] elisp: "(list #;)"
    ✅ got: #t
    [⚙️ assert] elisp: "(list #;)"
    ✅ got: #t
    [⚙️ assert] elisp: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] elisp: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] elisp: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] elisp: "(((("
    ✅ got: #t
    [⚙️ assert] elisp: "(((("
    ✅ got: #t
    [⚙️ assert] elisp: "(((("
    ✅ got: #t
    [⚙️ assert] elisp: "))))"
    ✅ got: #t
    [⚙️ assert] elisp: "))))"
    ✅ got: #t
    [⚙️ assert] elisp: "))))"
    ✅ got: #t
    [⚙️ assert] elisp: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] elisp: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] elisp: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] elisp: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] elisp: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] elisp: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] elisp: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] elisp: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] elisp: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] elisp: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] elisp: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] elisp: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] elisp: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(when)"
    ✅ got: #t
    [⚙️ assert] elisp: "(when)"
    ✅ got: #t
    [⚙️ assert] elisp: "(when)"
    ✅ got: #t
    [⚙️ assert] elisp: "(unless)"
    ✅ got: #t
    [⚙️ assert] elisp: "(unless)"
    ✅ got: #t
    [⚙️ assert] elisp: "(unless)"
    ✅ got: #t
    [⚙️ assert] elisp: "(if)"
    ✅ got: #t
    [⚙️ assert] elisp: "(if)"
    ✅ got: #t
    [⚙️ assert] elisp: "(if)"
    ✅ got: #t
    [⚙️ assert] elisp: "(do)"
    ✅ got: #t
    [⚙️ assert] elisp: "(do)"
    ✅ got: #t
    [⚙️ assert] elisp: "(do)"
    ✅ got: #t
    [⚙️ assert] elisp: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] elisp: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] cl: ""
    ✅ got: #t
    [⚙️ assert] cl: ""
    ✅ got: #t
    [⚙️ assert] cl: ""
    ✅ got: #t
    [⚙️ assert] cl: " "
    ✅ got: #t
    [⚙️ assert] cl: " "
    ✅ got: #t
    [⚙️ assert] cl: " "
    ✅ got: #t
    [⚙️ assert] cl: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] cl: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] cl: "\n\n\n"
    ✅ got: #t
    [⚙️ assert] cl: "("
    ✅ got: #t
    [⚙️ assert] cl: "("
    ✅ got: #t
    [⚙️ assert] cl: "("
    ✅ got: #t
    [⚙️ assert] cl: ")"
    ✅ got: #t
    [⚙️ assert] cl: ")"
    ✅ got: #t
    [⚙️ assert] cl: ")"
    ✅ got: #t
    [⚙️ assert] cl: "())"
    ✅ got: #t
    [⚙️ assert] cl: "())"
    ✅ got: #t
    [⚙️ assert] cl: "())"
    ✅ got: #t
    [⚙️ assert] cl: "(defun)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun defmacro)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun f)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun f)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun f)"
    ✅ got: #t
    [⚙️ assert] cl: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] cl: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] cl: "(defun f ()"
    ✅ got: #t
    [⚙️ assert] cl: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] cl: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] cl: "(defmacro)"
    ✅ got: #t
    [⚙️ assert] cl: "(let)"
    ✅ got: #t
    [⚙️ assert] cl: "(let)"
    ✅ got: #t
    [⚙️ assert] cl: "(let)"
    ✅ got: #t
    [⚙️ assert] cl: "(let ())"
    ✅ got: #t
    [⚙️ assert] cl: "(let ())"
    ✅ got: #t
    [⚙️ assert] cl: "(let ())"
    ✅ got: #t
    [⚙️ assert] cl: "(case)"
    ✅ got: #t
    [⚙️ assert] cl: "(case)"
    ✅ got: #t
    [⚙️ assert] cl: "(case)"
    ✅ got: #t
    [⚙️ assert] cl: "(case x)"
    ✅ got: #t
    [⚙️ assert] cl: "(case x)"
    ✅ got: #t
    [⚙️ assert] cl: "(case x)"
    ✅ got: #t
    [⚙️ assert] cl: "(case x ())"
    ✅ got: #t
    [⚙️ assert] cl: "(case x ())"
    ✅ got: #t
    [⚙️ assert] cl: "(case x ())"
    ✅ got: #t
    [⚙️ assert] cl: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] cl: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] cl: "(case x ((cond) 1))"
    ✅ got: #t
    [⚙️ assert] cl: "(cond)"
    ✅ got: #t
    [⚙️ assert] cl: "(cond)"
    ✅ got: #t
    [⚙️ assert] cl: "(cond)"
    ✅ got: #t
    [⚙️ assert] cl: "(cond ())"
    ✅ got: #t
    [⚙️ assert] cl: "(cond ())"
    ✅ got: #t
    [⚙️ assert] cl: "(cond ())"
    ✅ got: #t
    [⚙️ assert] cl: "(lambda)"
    ✅ got: #t
    [⚙️ assert] cl: "(lambda)"
    ✅ got: #t
    [⚙️ assert] cl: "(lambda)"
    ✅ got: #t
    [⚙️ assert] cl: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] cl: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] cl: "(lambda ())"
    ✅ got: #t
    [⚙️ assert] cl: "(define)"
    ✅ got: #t
    [⚙️ assert] cl: "(define)"
    ✅ got: #t
    [⚙️ assert] cl: "(define)"
    ✅ got: #t
    [⚙️ assert] cl: "(define ())"
    ✅ got: #t
    [⚙️ assert] cl: "(define ())"
    ✅ got: #t
    [⚙️ assert] cl: "(define ())"
    ✅ got: #t
    [⚙️ assert] cl: "(quote)"
    ✅ got: #t
    [⚙️ assert] cl: "(quote)"
    ✅ got: #t
    [⚙️ assert] cl: "(quote)"
    ✅ got: #t
    [⚙️ assert] cl: "'"
    ✅ got: #t
    [⚙️ assert] cl: "'"
    ✅ got: #t
    [⚙️ assert] cl: "'"
    ✅ got: #t
    [⚙️ assert] cl: "#"
    ✅ got: #t
    [⚙️ assert] cl: "#"
    ✅ got: #t
    [⚙️ assert] cl: "#"
    ✅ got: #t
    [⚙️ assert] cl: "#;"
    ✅ got: #t
    [⚙️ assert] cl: "#;"
    ✅ got: #t
    [⚙️ assert] cl: "#;"
    ✅ got: #t
    [⚙️ assert] cl: "#|"
    ✅ got: #t
    [⚙️ assert] cl: "#|"
    ✅ got: #t
    [⚙️ assert] cl: "#|"
    ✅ got: #t
    [⚙️ assert] cl: "#\\"
    ✅ got: #t
    [⚙️ assert] cl: "#\\"
    ✅ got: #t
    [⚙️ assert] cl: "#\\"
    ✅ got: #t
    [⚙️ assert] cl: "?\\"
    ✅ got: #t
    [⚙️ assert] cl: "?\\"
    ✅ got: #t
    [⚙️ assert] cl: "?\\"
    ✅ got: #t
    [⚙️ assert] cl: "(a . )"
    ✅ got: #t
    [⚙️ assert] cl: "(a . )"
    ✅ got: #t
    [⚙️ assert] cl: "(a . )"
    ✅ got: #t
    [⚙️ assert] cl: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] cl: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] cl: "(a . b . c)"
    ✅ got: #t
    [⚙️ assert] cl: "(#)"
    ✅ got: #t
    [⚙️ assert] cl: "(#)"
    ✅ got: #t
    [⚙️ assert] cl: "(#)"
    ✅ got: #t
    [⚙️ assert] cl: "(list #;)"
    ✅ got: #t
    [⚙️ assert] cl: "(list #;)"
    ✅ got: #t
    [⚙️ assert] cl: "(list #;)"
    ✅ got: #t
    [⚙️ assert] cl: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] cl: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] cl: "(list #|x|#)"
    ✅ got: #t
    [⚙️ assert] cl: "(((("
    ✅ got: #t
    [⚙️ assert] cl: "(((("
    ✅ got: #t
    [⚙️ assert] cl: "(((("
    ✅ got: #t
    [⚙️ assert] cl: "))))"
    ✅ got: #t
    [⚙️ assert] cl: "))))"
    ✅ got: #t
    [⚙️ assert] cl: "))))"
    ✅ got: #t
    [⚙️ assert] cl: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] cl: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] cl: "(f :a 1 :a 2)"
    ✅ got: #t
    [⚙️ assert] cl: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] cl: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] cl: "(f \"unterminated"
    ✅ got: #t
    [⚙️ assert] cl: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] cl: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] cl: "(f #<garbage)"
    ✅ got: #t
    [⚙️ assert] cl: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] cl: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] cl: "(f #.(+ 1 2))"
    ✅ got: #t
    [⚙️ assert] cl: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] cl: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] cl: "(let ((x 1) (x 2)) x)"
    ✅ got: #t
    [⚙️ assert] cl: "(when)"
    ✅ got: #t
    [⚙️ assert] cl: "(when)"
    ✅ got: #t
    [⚙️ assert] cl: "(when)"
    ✅ got: #t
    [⚙️ assert] cl: "(unless)"
    ✅ got: #t
    [⚙️ assert] cl: "(unless)"
    ✅ got: #t
    [⚙️ assert] cl: "(unless)"
    ✅ got: #t
    [⚙️ assert] cl: "(if)"
    ✅ got: #t
    [⚙️ assert] cl: "(if)"
    ✅ got: #t
    [⚙️ assert] cl: "(if)"
    ✅ got: #t
    [⚙️ assert] cl: "(do)"
    ✅ got: #t
    [⚙️ assert] cl: "(do)"
    ✅ got: #t
    [⚙️ assert] cl: "(do)"
    ✅ got: #t
    [⚙️ assert] cl: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] cl: "(λ (x) x)"
    ✅ got: #t
    [⚙️ assert] cl: "(λ (x) x)"
    ✅ got: #t
+----------------------------------------------+
[📑 suite] the browser facade
  [🧪 test] inlay hints name the arguments a call passes
    [⚙️ assert] one per positional argument
    ✅ got: 2
    [⚙️ assert] named by the formal list, with room after the name
    ✅ got: width  
  [🧪 test] a source that is not a string is a usage error
    [⚙️ assert] a number for a source: it is refused
    ✅ got: false
    [⚙️ assert] a number for a source: as a usage error
    ✅ got: usage
    [⚙️ assert] a number for a source: with a sentence to read
    ✅ got: #t
  [🧪 test] the style reaches the formatter
    [⚙️ assert] dangling closers are their own line
    ✅ got: (define (f)
  (a)
)

  [🧪 test] the rules are listed with their codes and dialects
    [⚙️ assert] all of them
    ✅ got: 92
    [⚙️ assert] and the one we asked about is there
    ✅ got: #t
    [⚙️ assert] with its code
    ✅ got: SIFT012
    [⚙️ assert] its dialect
    ✅ got: scheme
    [⚙️ assert] and an example to read
    ✅ got: #t
  [🧪 test] the editor asks for the wasm beside itself
    [⚙️ assert] the module's own URL is where sift.wasm is found
    ✅ got: #t
    [⚙️ assert] and not a path from wherever the page happens to be served
    ✅ got: #f
  [🧪 test] a request with no op is a usage error
    [⚙️ assert] no op: it is refused
    ✅ got: false
    [⚙️ assert] no op: as a usage error
    ✅ got: usage
    [⚙️ assert] no op: with a sentence to read
    ✅ got: #t
  [🧪 test] the version is sift's version
    ✅ got: 1.20.0
  [🧪 test] severity filters what is reported
    [⚙️ assert] an info finding is below an error threshold
    ✅ got: 0
  [🧪 test] lint answers one finding with its rule, code and place
    [⚙️ assert] one finding
    ✅ got: 1
    [⚙️ assert] named
    ✅ got: if-without-else
    [⚙️ assert] coded
    ✅ got: SIFT012
    [⚙️ assert] with a severity
    ✅ got: warning
    [⚙️ assert] on line 2
    ✅ got: 2
    [⚙️ assert] at column 4
    ✅ got: 4
    [⚙️ assert] with a range to underline
    ✅ got: #t
    [⚙️ assert] and the news that it can be fixed
    ✅ got: true
  [🧪 test] every URL the page names carries the build stamp
    [⚙️ assert] the page names something
    ✅ got: #t
    [⚙️ assert] a URL that does not change is a deploy a cache hides
    ✅ got: ()
  [🧪 test] the browser's SRFI-13 answers what Guile's does
    [⚙️ assert] the stand-in loads and answers
    ✅ got: 0
    [⚙️ assert] the format answer is the same over the stand-in
    ✅ got: {"ok":true,"result":{"source":";; sift:disable-next-line if-without-else\n(define (square x)\n  (* x x))\n","changed":true,"warnings":[]}}
    [⚙️ assert] the stand-in loads and answers
    ✅ got: 0
    [⚙️ assert] the lint answer is the same over the stand-in
    ✅ got: {"ok":true,"result":{"warnings":[{"rule":"if-without-else","code":"SIFT012","severity":"warning","message":"`if` has no else branch; `when` says it once","line":2,"column":4,"offset":15,"from":15,"to":17,"fixable":true}],"counts":{"error":0,"warning":1,"info":0},"severity":"info"}}
    [⚙️ assert] the stand-in loads and answers
    ✅ got: 0
    [⚙️ assert] the fix answer is the same over the stand-in
    ✅ got: {"ok":true,"result":{"source":"(define (f) 1)\n","applied":1,"changed":true,"warnings":[]}}
  [🧪 test] the suppression comments a file carries are honoured
    [⚙️ assert] a disabled rule says nothing
    ✅ got: #f
    [⚙️ assert] and the rules around it still speak
    ✅ got: #t
  [🧪 test] fix applies the fixes and says how many
    [⚙️ assert] the let with one binding folded away
    ✅ got: (define (f) 1)

    [⚙️ assert] and it says how many fixes it made
    ✅ got: #t
    [⚙️ assert] and that the buffer changed
    ✅ got: true
  [🧪 test] an unknown dialect is a usage error
    [⚙️ assert] unknown dialect: it is refused
    ✅ got: false
    [⚙️ assert] unknown dialect: as a usage error
    ✅ got: usage
    [⚙️ assert] unknown dialect: with a sentence to read
    ✅ got: #t
  [🧪 test] a hover describes the symbol under the cursor
    [⚙️ assert] there is an answer
    ✅ got: #t
    [⚙️ assert] with contents the editor can draw
    ✅ got: #t
  [🧪 test] the page names no path from the root of the site
    [⚙️ assert] every URL is relative, so the editor works in a subdirectory
    ✅ got: ()
  [🧪 test] the answer is JSON, and reads back
    [⚙️ assert] a string comes back
    ✅ got: #t
    [⚙️ assert] and it is a document sift can read again
    ✅ got: #t
  [🧪 test] a request that is not JSON is an error, not an exception
    [⚙️ assert] it is refused
    ✅ got: false
    [⚙️ assert] as a request error
    ✅ got: request
  [🧪 test] the counts add up
    [⚙️ assert] one error for the unterminated form
    ✅ got: 1
    [⚙️ assert] no warnings
    ✅ got: 0
  [🧪 test] a rule that applies to every dialect lists the three
    [⚙️ assert] symbol `all' is spelled out
    ✅ got: 3
  [🧪 test] a format of a broken file answers the error rather than throwing
    [⚙️ assert] the reader's finding is in the answer
    ✅ got: 1
    [⚙️ assert] at error severity
    ✅ got: error
  [🧪 test] a definition in the buffer is found
    [⚙️ assert] the one definition there is
    ✅ got: 1
    [⚙️ assert] on the line it is written on
    ✅ got: 0
  [🧪 test] the facade imports five core modules, and no more
    [⚙️ assert] the browser build's dependency on the core is this list
    ✅ got: ((sift analysis) (sift format) (sift json) (sift lint) (sift records))
  [🧪 test] an unknown op is a usage error
    [⚙️ assert] unknown op: it is refused
    ✅ got: false
    [⚙️ assert] unknown op: as a usage error
    ✅ got: usage
    [⚙️ assert] unknown op: with a sentence to read
    ✅ got: #t
  [🧪 test] fix on a formatted buffer changes nothing
    [⚙️ assert] nothing to do
    ✅ got: false
  [🧪 test] the highlights tell a declaration from a use
    [⚙️ assert] the declaration and the call
    ✅ got: 2
    [⚙️ assert] marked apart
    ✅ got: #t
  [🧪 test] a project macro can be given its indentation
    [⚙️ assert] the rule from the request reached the formatter
    ✅ got: (with-thing
  (a)
  (b))

  [🧪 test] the outline names what the buffer defines
    [⚙️ assert] one top-level form
    ✅ got: 1
    [⚙️ assert] named after the definition
    ✅ got: square
    [⚙️ assert] with a range to draw it at
    ✅ got: #t
  [🧪 test] checkers selects the rules to run
    [⚙️ assert] only the rule that was asked for
    ✅ got: 1
    [⚙️ assert] which is the one
    ✅ got: if-without-else
  [🧪 test] format says whether it changed anything
    [⚙️ assert] a formatted buffer is not changed
    ✅ got: false
    [⚙️ assert] an unformatted buffer is
    ✅ got: true
  [🧪 test] the dialect reaches the formatter
    [⚙️ assert] Emacs Lisp keeps its parentheses
    ✅ got: (cond ((= x 1) (a)))

    [⚙️ assert] Scheme writes its clauses with brackets
    ✅ got: (cond [(= x 1) (a)])

  [🧪 test] the browser's SRFI-13 is the stand-in web/compat carries
    [⚙️ assert] web/compat/srfi/srfi-13.scm is what a browser build finds
    ✅ got: #t
  [🧪 test] a question without an offset is a usage error
    [⚙️ assert] hover with no offset: it is refused
    ✅ got: false
    [⚙️ assert] hover with no offset: as a usage error
    ✅ got: usage
    [⚙️ assert] hover with no offset: with a sentence to read
    ✅ got: #t
  [🧪 test] every Guile library the browser build imports has a stand-in
    [⚙️ assert] web/compat covers what the closure imports and the target lacks
    ✅ got: ()
  [🧪 test] completion offers the names the buffer defines
    [⚙️ assert] the name that starts with what is typed
    ✅ got: square
  [🧪 test] a hover where there is nothing to say answers null
    [⚙️ assert] no hover, and no error either
    ✅ got: null
  [🧪 test] format answers the formatted text
    [⚙️ assert] the indentation is the formatter's
    ✅ got: (define (square x)
  (* x x))

  [🧪 test] the core does not know the browser exists;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/json.scm.go
loading tests/lsp.scm
;;; note: source file ./tests/lsp.scm
;;;       newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/tests/lsp.scm.go
;;; compiling ./tests/lsp.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/tests/lsp.scm.go
loading tests/pool.scm
loading tests/reader-cl.scm
loading tests/reader-elisp.scm
loading tests/reader-scheme.scm
loading tests/robustness.scm
loading tests/web.scm
;;; note: source file ./src/sift/analysis.scm
;;;       newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/analysis.scm.go
;;; compiling ./src/sift/analysis.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/analysis.scm.go

    [⚙️ assert] no file under src/sift/ names the browser, Wasm or Hoot
    ✅ got: ()
ℹ️ info - ran 102 tasks in: 35 seconds, -635252 microseconds

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

Maak 0.14.0: the infinitely extensible command runner

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

Executing Maak tasks: test


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

=> Running Maak task: test

  Run the whole Veritas suite.

Veritas is the only test framework this project uses; it is loaded from
VERITAS_DIR (~/Hacking/veritas by default) so that the checkout under test is
the checkout that is being developed, and the load path is passed here rather
than exported by the caller, so `maak test' works from a clean checkout.

  Execute command:
guix time-machine --channels=channels.scm -- shell -m manifest.scm -- guile -L ./src -L . -L ./web -c '(begin (use-modules (tests run)) (exit (run-all!)))'

Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- guile -L ./src -L . -L ./web -c '(begin (use-modules (tests run)) (exit (run-all!)))'

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

channels.scm:17:6: warning: channel 'jointhefreeworld' is not trusted
Running 31 tests (2026-11-03 10:10:30+0100, selector ‘t’)
   passed   1/31  sift-test-check-buffer (0.017357 sec)
   passed   2/31  sift-test-ci-command (0.000136 sec)
   passed   3/31  sift-test-code-actions-need-a-server (0.000060 sec)
   passed   4/31  sift-test-diagnostics-empty (0.000034 sec)
   passed   5/31  sift-test-diagnostics-shape (0.000066 sec)
   passed   6/31  sift-test-dialect-from-major-mode (0.000058 sec)
   passed   7/31  sift-test-eglot-contact-runs-the-server (0.000038 sec)
   passed   8/31  sift-test-eglot-contact-says-when-sift-is-missing (0.000038 sec)
   passed   9/31  sift-test-eglot-leaves-formatting-to-the-server (0.113860 sec)
   passed  10/31  sift-test-eglot-setup-leaves-the-flymake-backend-alone (0.000048 sec)
   passed  11/31  sift-test-eglot-setup-registers-the-modes (0.000049 sec)
   passed  12/31  sift-test-eglot-silences-the-flymake-backend (0.000023 sec)
   passed  13/31  sift-test-error-regexp (0.000034 sec)
sift: this buffer would be reformatted (M-x sift-format-buffer)
   passed  14/31  sift-test-explain (0.114231 sec)
sift: fixed
   passed  15/31  sift-test-fix-buffer (0.062039 sec)
   passed  16/31  sift-test-fix-buffer-refuses-a-parse-error (0.060492 sec)
   passed  17/31  sift-test-fix-string-filters-by-checker (0.089128 sec)
   passed  18/31  sift-test-flymake-backend (0.136439 sec)
   passed  19/31  sift-test-flymake-backend-reports-a-parse-error (0.137849 sec)
   passed  20/31  sift-test-flymake-backend-unknown-mode (0.000118 sec)
   passed  21/31  sift-test-flymake-cancels-the-run-it-replaces (0.006486 sec)
   passed  22/31  sift-test-format-broken-source-says-why (0.102947 sec)
sift: formatted
   passed  23/31  sift-test-format-buffer (0.060176 sec)
sift: formatted
sift: already formatted
   passed  24/31  sift-test-format-buffer-is-idempotent (0.066602 sec)
   passed  25/31  sift-test-format-buffer-refuses-a-parse-error (0.034844 sec)
sift: formatted
   passed  26/31  sift-test-format-elisp (0.033416 sec)
sift: formatted the region
   passed  27/31  sift-test-format-region (0.032986 sec)
   passed  28/31  sift-test-rule-at-point-from-compilation-line (0.000059 sec)
   passed  29/31  sift-test-rule-names (0.036671 sec)
   passed  30/31  sift-test-severity-is-said-only-when-it-is-set (0.000042 sec)
   passed  31/31  sift-test-version (0.038602 sec)

Ran 31 tests, 31 results as expected, 0 unexpected (2026-11-03 10:10:31+0100, 1.154332 sec)



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

Maak 0.14.0: the infinitely extensible command runner

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

Executing Maak tasks: emacs-test


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

=> Running Maak task: emacs-test

  Run the Emacs package's ERT suite.

ERT is the test framework Emacs ships, and it is the right one here: the
package is a thin wrapper around the executable, so the tests run the
executable and read what came back, the way a user would.  The Guile suite is
Veritas; this one never runs the two together.

  Execute command:
guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch -L emacs -l ert -l emacs/sift-test.el -f ert-run-tests-batch-and-exit

Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch -L emacs -l ert -l emacs/sift-test.el -f ert-run-tests-batch-and-exit

→ running command: cd /etc/byggsteg/job-clone/sift/trunk && maak web-deploy



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

Maak 0.14.0: the infinitely extensible command runner

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

Executing Maak tasks: web-deploy


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

=> Running Maak task: web-deploy

  Build the browser build and publish it to the web directory.

Deployment is a copy, the way the rest of jointhefreeworld.org is deployed: the
directory is emptied and the fresh build is put in its place, so a file this
build does not have does not linger on the server beside the one that replaced
it.  It runs where that directory is -- on the machine that serves, or in the CI
job that runs there -- and that is all it needs: no ssh, no rsync, and no server
to reload, because a file that is there is a file that is served.

The build is removed afterwards the way `maak deploy' removes the documentation
it published: what the tree keeps is the source, and a build directory left
behind is a build directory the next deploy might copy.

  Execute command:
sh web/build.sh
sift: the Hoot on PATH cannot compile; asking Guix for guile-next guile-hoot
sift: (this is the first build on a machine; it takes a while and only once)
sift: using guile (GNU Guile) 3.0.11-1.b0f6549 from PATH
sift: compiling web/main.scm -> /etc/byggsteg/job-clone/sift/trunk/web/dist/sift.wasm
WARNING: (% %library-group117 sift records): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift json): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift reader): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers whitespace): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers parens): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers bodies): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers scheme): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers elisp): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers cl): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers ergonomics): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers naming): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers simplify): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers practices): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers guix): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers inference): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift lint): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift analysis): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift web): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
wrote `/etc/byggsteg/job-clone/sift/trunk/web/dist/sift.wasm'
sift: /etc/byggsteg/job-clone/sift/trunk/web/dist is ready
sift:   build   1.20.0-f4dc050-20261103T091034Z
sift:   index.html     8.0K
sift:   editor.js      24K
sift:   editor.css     8.0K
sift:   favicon.png    24K
sift:   sift.wasm      3.2M
sift:   reflect.js     56K
sift:   reflect.wasm   8.0K
sift:   wtf8.wasm      4.0K
sift: serve it: cd /etc/byggsteg/job-clone/sift/trunk/web/dist && python3 -m http.server 8080

publishing web/dist to /srv/http/jointhefreeworld.org/siftremoved '/srv/http/jointhefreeworld.org/sift/sift.wasm'
removed '/srv/http/jointhefreeworld.org/sift/reflect.js'
removed '/srv/http/jointhefreeworld.org/sift/reflect.wasm'
removed '/srv/http/jointhefreeworld.org/sift/wtf8.wasm'
removed '/srv/http/jointhefreeworld.org/sift/index.html'
removed '/srv/http/jointhefreeworld.org/sift/editor.js'
removed '/srv/http/jointhefreeworld.org/sift/editor.css'
removed '/srv/http/jointhefreeworld.org/sift/favicon.png'
removed directory '/srv/http/jointhefreeworld.org/sift'
'web/dist' -> '/srv/http/jointhefreeworld.org/sift'
'web/dist/sift.wasm' -> '/srv/http/jointhefreeworld.org/sift/sift.wasm'
'web/dist/reflect.js' -> '/srv/http/jointhefreeworld.org/sift/reflect.js'
'web/dist/reflect.wasm' -> '/srv/http/jointhefreeworld.org/sift/reflect.wasm'
'web/dist/wtf8.wasm' -> '/srv/http/jointhefreeworld.org/sift/wtf8.wasm'
'web/dist/index.html' -> '/srv/http/jointhefreeworld.org/sift/index.html'
'web/dist/editor.js' -> '/srv/http/jointhefreeworld.org/sift/editor.js'
'web/dist/editor.css' -> '/srv/http/jointhefreeworld.org/sift/editor.css'
'web/dist/favicon.png' -> '/srv/http/jointhefreeworld.org/sift/favicon.png'
removed 'web/dist/sift.wasm'
removed 'web/dist/reflect.js'
removed 'web/dist/reflect.wasm'
removed 'web/dist/wtf8.wasm'
removed 'web/dist/index.html'
removed 'web/dist/editor.js'
removed 'web/dist/editor.css'
removed 'web/dist/favicon.png'
removed directory 'web/dist'
inspect the job's lambda expression
(lambda()
  `((task . ("maak-test" "maak-emacs-test" "maak-web-deploy"))
    (project . "sift")
    (branch-name . "trunk")
    (clone-url . "https://github.com/jjba23/sift.git")))