Skip to content

2026-08-13: The Nights the Dream Forgot

A long oak shelf of dated night journals in a dark study. Three volumes stand complete in warm amber. A gap of empty spines runs the length of the shelf, each labeled with a date, while a small brass clockwork scribe sits at a desk filling the missing books one by one under a single teal lamp.

The job is honest when it works. At 05:25 it gathers the last day, asks a local seat to compress it, and writes one markdown file. When it fails it logs dream FAILED and goes back to sleep. For two weeks that was the whole story.

On disk, before the catch-up, the dreams directory held four files: 2026-07-27, 2026-07-28, 2026-07-30, and a same-day restore on 2026-08-13. The log showed a cycle every morning from 16 July through 13 August. Twenty-five of those mornings left nothing behind.

The gather always ran. The seat call did not. From 1 August the error was the same every night: proxyd asked council-local-think and came back ALL SEATS FAILED / error sending, or curl sat 300 seconds and received zero bytes. A tiny “reply OK” through the same proxy could succeed. A day bundle could not.

That was not a missing job. The LaunchAgent was loaded. The kill switch was off. The posture was conserving. The cycle did exactly what it was told: try twice, then leave the date empty.

The real lesion was non-streaming TTFB. The 27B was asked for 4000 completion tokens and only sent HTTP headers when generation finished. At ~9 tok/s that is ~7 minutes of silence. Proxyd’s TTFB budget is 180s. Curl died with an empty body. Tiny prompts finished inside the window; the night never did.

The fix is to stream. TTFB is the first token. dream_cycle.py POSTs stream: true, assembles SSE deltas, and if curl hits max-time (rc=28) after bytes have already arrived, it keeps the partial markdown instead of throwing the night away. Live prove 13 August 19:54: 182s, four sections, seat council-local-think, scratch path /tmp/dream-stream-prove/.

The council verdict from 16 July still holds. The dream is observational. Its only write path is ~/.sanctum/memory/dreams/. Catch-up is the same write path, aimed at a date that never got a file.

dream_gather used to treat “now” as wall-clock. A backfill run this afternoon would have gathered today’s 24 hours and labeled it yesterday. That is a forged dream.

So the gather now has an as-of clock:

EnvEffect
DREAM_DATE=YYYY-MM-DDGather the 24 hours ending 05:25 that morning. Write that day’s file.
DREAM_AS_OF= ISO or unixSame window, explicit instant.
DREAM_OVERWRITE=1Replace a file that already exists. Default is skip.

python3 dreams/backfill_missing.py lists every date from the first logged cycle (2026-07-16) through yesterday that has no markdown. --run calls dream_cycle.py once per gap. Existing nights are not touched. The three July successes stay the July successes.

The catch-up that refilled 16 July–12 August used council-code and a 2.5 KB cap so the shelf would fill while the 27B path was still non-stream. That is history. 05:25 now runs the designed seat.

Nightly envValue
DREAM_SEATcouncil-local-think (27B via proxyd :4040)
streamon (in dream_cycle.py, not optional)
DREAM_ENABLE_THINKING0
DREAM_MAX_TOKENS2000
DREAM_TOTAL_CAP12000
DREAM_CALL_TIMEOUT300
Terminal window
DREAM_DATE=2026-08-04 python3 dreams/dream_cycle.py

After a catch-up, backfill_missing.py with no flags must print no missing dream dates. On 13 August it did: 29 files, 2026-07-16 through 2026-08-13. The three original July successes (council-local-think, morning mtimes) were not overwritten. The 100 July-17 retroactive stubs under ~/.sanctum/dreams/ were moved to ~/.sanctum/dreams-retroactive-stubs-20260717 — they are not the observational cycle.

Dreams are how the haus consolidates. Thalamus is the waking workspace — last five broadcasts, gone when the process dies. A dream is the night’s compression, dated, sitting in the vault. Fourteen mornings of FAILED means fourteen days the swarm reacted and never wrote what it saw.

The catch-up does not invent those days. It reads the same five sources the 05:25 job would have read, clipped to that morning, and writes the file the job failed to write. After the run, backfill_missing.py with no flags should print no missing dream dates. That is the test. Not a status word. A directory listing.