<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/modules/agenda-query.el, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-07-31T16:04:42+00:00</updated>
<entry>
<title>feat(agenda): refresh the render cache on a timer, without the daemon</title>
<updated>2026-07-31T16:04:42+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-31T16:04:42+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=445a0be315f3d6fff585f1558262fb5dacd10d12'/>
<id>urn:sha1:445a0be315f3d6fff585f1558262fb5dacd10d12</id>
<content type='text'>
The surface reading this has to stay correct while Emacs is down, and
emacsclient is exactly the thing that cannot. So the writer is a batch
Emacs and a user timer runs it every five minutes.

- scripts/agenda-render-cache writes the cache from a batch Emacs. It
  resolves the agenda file list through the config's own resolver rather
  than restating it, so adding a calendar source stays a one-place change.
- The timer uses OnCalendar so Persistent actually applies. On a monotonic
  schedule it is silently ignored, and a machine that slept would come back
  to a stale file with nothing to trigger a catch-up.
- The window is now three days, yesterday through tomorrow. A consumer
  drawing a rolling window centred on now has nothing to draw for the part
  of its span outside today, which late in the evening is half the surface.

The keyword list moved to user-constants, where a batch Emacs can reach it
without this config's package dependencies. Without it org did not
recognise DOING or VERIFY, so it stopped parsing those headlines as tasks
at all: the keyword and priority cookie stayed glued to the front of every
title and each row reported no keyword and not-done. The file parsed
cleanly and was wrong, which is the failure worth guarding.

The bats tests run against a fixture and this checkout, not the machine's
real agenda and installed config. Asserting over live data let the same
suite pass on a day that happened to have no keyworded entries.
</content>
</entry>
<entry>
<title>feat(agenda): add the renderer output profile and its cache file</title>
<updated>2026-07-31T14:59:29+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-31T14:59:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=37f21839ca62617fef07684b2f98268de47a71c2'/>
<id>urn:sha1:37f21839ca62617fef07684b2f98268de47a71c2</id>
<content type='text'>
The surface that reads this went live, and it reads a different shape than
the canonical profile emits.

- cj/agenda-render-json adds s and e in epoch milliseconds, plus t for the
  title. The canonical fields ride along, so one file serves both readers.
- Every row gets an end it can be drawn with. An all-day entry spans its
  day. A point event has zero width. The canonical profile still reports
  null there, which is faithful to the source but not a width.
- cj/agenda-render-cache-update writes today to the XDG cache path.

Input stays epoch seconds on both profiles. Only the output converts, and
the guards that catch a milliseconds-for-seconds caller still apply.

Nothing schedules the cache write yet, so the file is only as fresh as its
last call. Picking a refresh mechanism is its own decision.
</content>
</entry>
<entry>
<title>feat(agenda): query the agenda window as JSON for external renderers</title>
<updated>2026-07-31T14:39:11+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-31T14:39:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=55e980fe28112e636a6d3165979f161d1a6038ab'/>
<id>urn:sha1:55e980fe28112e636a6d3165979f161d1a6038ab</id>
<content type='text'>
I need the agenda drawable from outside Emacs, on a 24-hour axis that
refreshes every few minutes.

- cj/agenda-window-json returns every entry intersecting an epoch-second
  window.
- Epoch seconds keep timezone out of the interface. The consumer converts
  per city, so DST weeks stop being a special case.
- Repeating entries expand to one row per occurrence through org's own
  arithmetic, so they land where my agenda shows them.
- Given an out-path it writes atomically. A reader on a timer never sees a
  half-written file.
- It skips archived and commented subtrees, as the agenda does.

The trap: SCHEDULED and DEADLINE are properties on the planning element,
not children in the parse tree. Mapping over 'timestamp returns neither,
and does it silently. An agenda is mostly made of those two. The tests pin
it with a fixture carrying no body timestamp.
</content>
</entry>
</feed>
