The trio the author decided on 2026-09-20 is now all built: def is CL's
defparameter — its initialiser runs on every daemon re-run, unguarded, so
an edited initialiser repaints the same storage on C-c C-c plus re-run —
defonce (Clojure's name for CL's defvar, per the author) initialises once
behind the .init~once. flag, and defconst stays the image.
One parse arm reads both forms; the difference is Ast.reinit, carried to
Tast.global's grerun. Emit.startup_plan gives a def no guard flag, and
Check.check_global lifts every def initialiser — zero and literal
included — into global/<n>, so the host's startup reaches it through the
function cell and a re-evaluated def swaps it (Session's def_inits;
Emit.redefinition declares the cell for a non-sibling target). The old
defvar spelling is refused with the rename and both compiling spellings,
and every program, test, doc and editor list is swept — except sand.flan,
the author's live WIP, whose seven defvar lines are flagged in FIX.org
and keep its three dependent tests red on this branch.
The path was ceremony. Under [flan dev] the daemon already decides where it
wants to talk to the program and writes it into FLAN_AGENT_SOCKET, which the
C side has always honoured over whatever the source named — so the argument
was a value nothing read. Outside the daemon any path will do as long as the
program says which one it picked.
So [start] becomes a macro over two functions: no argument picks the
daemon's socket if there is one and otherwise /tmp/flan-agent-<pid>-<clock>.sock,
announced on stderr because a socket nobody can name is a socket nobody can
connect to. The explicit form stays for a program that wants a fixed path.
Extra arguments are spliced into [start-at] rather than dropped, so the arity
refusal is still the checker's, at the call site.
And the socket is removed on the way out. The bind stashes the path it bound
and registers an atexit; the two paths that leave by _exit — the break loop's
[abort] and the orphan handler — unlink it by hand, as the orphan handler
already did for its own copy of the path. Nothing else takes it away: under
the daemon it sits in a temp directory that is still never removed (FIX.org),
and outside there is no daemon at all.
test/programs/dev-loop.flan now names no socket, which puts the whole daemon
block in test_dev.ml behind the zero-argument form; agent-auto.flan is the
standalone half, reached only through the line the program printed, and it
pins the second (agent/start) as a no-op and the socket as gone at exit.