Something a model could not do, and so wrote a note about instead

Asked to remind somebody every Monday, a model looked down its tool list, found
notes_create described as "something worth having in a later conversation" and
memory_add beginning with the word Remember, wrote a note, and reported that it
had scheduled something. Every screen agreed with it. There was no scheduling
tool at all -- the near-misses were the only thing there was to reach for, and
nothing anywhere said the thing it was being asked for existed.

The seam had been left open on purpose: Schedule.origin has defined
ORIGIN_MODEL, with no writer, since scheduling shipped, and services/schedules.py
says in its first line that it holds what the routes *and the tools* both need.
This is the tool that was meant to go through it.

Four of them, and a thin layer: rule.validate is still the one total normaliser
the form and the compile share, schedules.create still writes the row and the
task chat together, and rule.describe still says what came out. A second dialect
for models would mean two definitions of "every other Tuesday" and one of them
going quietly wrong.

The result is that description, never "done". A schedule is invisible until it
fires, which may be days away, so the sentence in the reply is the only moment
anybody can check that Monday was read as Monday -- and the tool says so, in the
text the model reads back. The list badges the ones nobody typed.

Gated on schedule.use rather than a permission of its own: somebody who may set
one up by hand may say so to a model instead, and a second checkbox beside the
first would only ever be answered "the same as that one".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaroslav Beneš
2026-08-06 10:28:05 +02:00
parent 14b1428f9f
commit feca8861a1
10 changed files with 955 additions and 12 deletions
+7 -4
View File
@@ -20,7 +20,7 @@ lembas info # paths + counts, useful when confused
lembas secret-key # generate LEMBAS_SECRET_KEY
lembas create-admin # create or promote an admin
pytest # 1854 tests, ~2min
pytest # 1872 tests, ~2min
# PLAN.md tracks what is and is not built
ruff check . # lint (line length 100)
python scripts/build_artwork.py # regenerate artwork (SVG + PWA icons;
@@ -128,7 +128,8 @@ src/lembas/
schedule/ work that happens because time passed: clock.py (whose
"now"), rule.py (the recurrence, pure and total),
ticker.py (the loop and the claim), runner.py (firing),
compile.py (plain words into a rule)
compile.py (plain words into a rule), tool.py (the four
a model calls)
wake.py starting a reply from outside a request -- one lock
discipline, shared by finished jobs and by schedules
sharing.py one visibility rule for every library store
@@ -178,8 +179,10 @@ touching the code it names -- these are the same notes, not a summary.
harness fragments, SSH, background jobs, the file tools and the patch matcher,
the project listing and a project's own AGENTS.md, and the terminal panel.
- `docs/notes/schedules-and-reports.md` -- claiming a schedule before firing it,
the pure recurrence rule, the wake lock, task chats, Reports, and why an empty
`kind` means both sides of the sidebar switch and never "no filter".
the pure recurrence rule, the wake lock, task chats, Reports, why an empty
`kind` means both sides of the sidebar switch and never "no filter", and the
four scheduling tools a model calls (which did not exist, so a model asked to
schedule something wrote a note and said it had).
- `docs/notes/image-generation.md` -- the ComfyUI workflow with holes in it, what
substitution walks, the review-and-retry loop, and how a failure reports itself.