Commit Graph
9 Commits
Author SHA1 Message Date
kristianwindandClaude Opus 5 f400705bb7 fix(release): tagbeskeden når frem til udgivelsen
Den skulle have gjort det siden #72, og gjorde det ikke. v0.45.0 og v0.46.0 fik
begge flettecommittens overskrift som udgivelsestekst — uden at noget fejlede,
og uden at nogen kunne se det andet end på siden bagefter.

`fetch-depth: 0` er ikke nok. actions/checkout henter først alle tags korrekt og
overskriver derefter netop den ene, der udløste kørslen:

    git rev-parse refs/tags/v0.46.0
    git fetch --no-tags origin +0dc4c2f9b8…:refs/tags/v0.46.0

Den henter commit-SHA'en ind i tag-refen. Den annoterede tag bliver dermed til
en letvægtstag, der peger direkte på commit'en, og `%(contents)` giver så
commitbeskeden. Kommentaren i filen sagde, at en overfladisk checkout var
problemet; det var rigtigt og utilstrækkeligt.

Tagget hentes derfor som *ref* igen, lige før det læses.

Og vagten: hver tagbesked begynder med sin egen version, så holder det ikke,
læser vi noget andet end tagget, og kørslen fejler frem for at udgive en forkert
tekst. Det er det, der manglede — fejlen var ikke svær at rette, den var svær at
opdage.

Målt i et klonet arbejdstræ i alle tre tilstande: annoteret giver den rigtige
tekst med selvlinket fjernet, letvægt giver flettecommitten og udløser vagten,
og en re-fetch af refen bringer den annoterede tilbage.

Teksten på de to udgivelser, der allerede stod forkert, er rettet i hånden.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 08:21:27 +02:00
kristianwindandClaude Opus 5 70d7398d5a docs: skriv det ned, der er blevet bygget
API-dokumentationen har fulgt med hele vejen — der er en prøve, der fejler,
hvis en rute ikke står i openapi.yaml, og den fangede mig fire gange i går.
Brugervejledningen har ikke fulgt med, og det er den, folk læser.

Nyt: en side om beskeder — hvad der udløser en, hvorfor gentagne
rettelser bliver slået sammen, push pr. apparat og mærket på ikonet. En
om at åbne links i en anden browser, som mest af alt handler om, hvad en
webside ikke kan: hverken se hvilke browsere der findes eller vælge
mellem dem. Og en om tællingen af installationer, som ikke stod nogen
steder overhovedet — en melding, der er slået til som udgangspunkt, har
en pligt til at være skrevet ned, også når ingen har spurgt.

Rettet: AI-siden beskrev to funktioner, hvor der nu er syv, og
listen over hvad der sendes hvorhen var derfor forkert som en påstand om
noget privat. Noter-siden manglede deling med en e-mailadresse og hvad
`@Sofie` gør. Mail-siden manglede den anden vej ind i indbakken.
Konfigurationen sagde stadig, at versionstjekket kun kunne se efter.

Og tagbeskeden når nu frem. Den ER annonceringen — skrevet på produktets
eget sprog til dem, der bruger det — og udgivelsen på GitHub blev fyldt
med en autogenereret liste over commit-overskrifter i stedet, som er
skrevet til dem, der læser koden. Nu står teksten øverst og listen under
den. Linjen med linket til udgivelsen selv tages af: en side, der linker
til sig selv, hjælper ingen.

Dokumentationen bygges nu også på en PR. `mkdocs build --strict` fejler
på et link til en side, der ikke findes, og at bygge først efter merge er
at få det at vide på main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 08:52:54 +02:00
Kristian WindandClaude Opus 5 6853897d00 ci: install WebKit as well, for the one test that needs it
The `webkit-forms` project was added to the Playwright config and CI was not told,
so it installed Chromium and the one WebKit test died on a missing executable —
26 passed, 1 failed, and the failure said nothing about the app.

It is one test on purpose. The suite stays Chromium, because running it in three
engines finds the same breakage three times; focus is the exception, and Safari
ignoring `autofocus` on anything inserted after load is what made "sections have
no function" true from inside Safari.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 10:05:29 +02:00
Kristian WindandClaude Opus 5 0dbea0ea4b feat: make it possible to see which version is actually running
Release / Build and publish image (push) Failing after 9m56s
"I have updated and restarted, but I cannot tell whether it worked" is
not a question the panel could answer. The version was on the startup
line and in the settings page, and nowhere you can reach from outside.

/healthz carries it now. That is the one endpoint answering without a
session, which makes it the only way to ask the question from a terminal
or from the panel itself. The "listening" line repeats it too, because
that is the line the Rune's done_regex matches and therefore the one
sitting at the bottom of the console after a deploy.

The update notice could also never have worked. It reads GitHub's
releases/latest, and this repository had only tags — a tag is not a
release, and that endpoint answers 404 for a repository without any. The
release workflow creates one now, after the image is pushed so a release
never announces a version that failed to build.

VERDANDE_UPDATE_CHECK is a Rune variable, so it can be switched on
without editing the container. Still off by default: it is an outbound
request, and that is a choice to make rather than a default to inherit.

Rune version 1 -> 2, so the panel offers the update.

Note that the check still cannot see anything while the repository is
private — releases/latest is 404 anonymously, exactly as the GHCR package
was. Making the repo public, or teaching the check to carry a token, is a
separate decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 14:35:36 +02:00
Kristian WindandClaude Opus 5 cb77990458 docs(api): an OpenAPI spec, checked against the router
The brief asked for one. docs/api.md is complete and hand-written, and
there was nothing a tool could read.

Written by hand rather than generated from annotations, which would have
meant every handler carrying a second copy of itself in a comment. The
risk with a hand-written spec is that it goes stale, so it does not
depend on anybody remembering: openapi_test.go walks the chi router and
fails both on a route nothing describes and on a description with no
route behind it. CI separately checks it is a valid OpenAPI document.

The test reads the file with a forty-line scanner rather than pulling in
a YAML library. It needs two things — which paths are listed and which
methods each has — and both sit at fixed indentation in a document the
test also owns, which is worth more than a dependency in a project whose
whole shape is one static binary.

The CalDAV routes are excluded deliberately: PROPFIND and REPORT are
outside what OpenAPI can describe, and docs/caldav.md covers them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 10:56:33 +02:00
Kristian WindandClaude Opus 5 1424f43a40 test(e2e): smoke tests that drive the real binary
The brief asked for these under Definition of done and they were never
written. 610 Go tests, none of which opens a browser.

Six flows: create the first account and sign in, quick add and tick a
task off, click every link in the sidebar, open a task and edit it, walk
every settings tab, and check that the manifest's icons and the service
worker can actually be fetched. Every assertion is on rendered content
rather than on a URL — the binary serves the SPA shell for anything it
does not recognise, so toHaveURL passes on precisely the bug this exists
to catch.

The suite builds the frontend, copies it into cmd/verdande/webbuild and
starts the real binary, every run. Merely starting the server would test
whatever frontend was copied there last, which during development is
nearly always the wrong one, and a green report on code that is not
running is worse than no report.

Chromium only. A smoke test catches a build that does not work at all;
running it in three engines finds the same breakage three times.

They found four bugs the first time they ran, fixed in the commits before
this one: concurrent writes returning SQLITE_BUSY, a completed task
keeping its row, the same task landing in the list twice, and a database
failure presenting as everybody being logged out.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 10:56:33 +02:00
Kristian WindandClaude Opus 5 ba5892fa9e fix(docs): pin the toolchain in a requirements file so pip caching works
actions/setup-python's pip cache needs a requirements.txt or
pyproject.toml to hash, and failed the whole job without one. Putting
the pin in a file rather than inline also puts it somewhere a person
would look for it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 08:11:26 +02:00
Kristian WindandClaude Opus 5 7c9bde2cfd docs(phase6): documentation site, landing page and open-source scaffolding
Material for MkDocs under docs/, covering self-hosting, the Rune, the
quick-add and filter languages, importing from Todoist, CalDAV,
mail-to-task, MCP, the AI layer and the API. The version is pinned: the
maintainers have announced that MkDocs 2.0 removes the plugin system
with no migration path, and an unpinned install would break this build
on the day it lands.

The landing page shows the quick-add parser as actual text rather than a
screenshot of it — that is the thing worth showing, and it reads better
as the real thing. It shares the app's design tokens, so the site and
what it describes look like one project.

MIT licence, contributing guide, security policy and issue templates.
Pages deployment is behind workflow_dispatch, so the docs build on every
push but nothing is published until the owner chooses to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 08:08:36 +02:00
Kristian WindandClaude Opus 5 02c8b1be61 feat(server): runnable binary, Rune manifest, Docker image and CI
The HTTP server serves /healthz, the API namespace and the PWA, with the
frontend embedded behind a build tag so a clean checkout compiles without
a Node toolchain. /healthz reads the database rather than just answering:
a process that cannot reach its own data is not healthy, and a 200 there
would keep a broken container in rotation.

The image is distroless and static — the SQLite driver is pure Go, so
CGO stays off. The Rune manifest uses keep_entrypoint because there is
no shell in the image to run a startup command with, and its log watchers
match the JSON log format the container actually emits.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 23:05:26 +02:00