2026-08-29 · Updated 2026-08-29 · 10 min read
Task state as durable agent memory
A citable definition of task memory for coding agents: the durable record a fresh process reads to recover work and writes to deposit progress — defined against chat history and vector stores, with the freshness and scope rules that keep it trustworthy.
By Juno AI INC · yylo-ledger · task-truth
Every agent that works unattended eventually meets the same cold start: a fresh process, a terminal that scrolled away hours ago, and one question — what was happening here, and where did it stop? Answering from a conversation works only while the conversation survives, and conversations do not survive. Answering from a ticket system works only while someone keeps the tickets synchronized with the repository, and nobody does. The answer that holds is a different artifact: task state treated as memory — a durable, addressable record of the work that any later process can read to recover exactly what was asked, what was claimed, what finished, and what remains, and can write to deposit its own account when it acts.
This page is the reference definition of that artifact, with its boundaries stated explicitly. It is not the argument for adopting task truth — the task-truth introduction makes that case and names the four semantics underneath it — and it is not the auditor's procedure for walking one task's records end to end, which the task-evidence guide owns. What it owns is narrower and more reusable: which qualities turn state into memory, which disqualify an artifact that merely resembles it, and the freshness and scope rules a memory substrate needs before an agent may trust it. Every behavior claimed below was checked against the YYLO Ledger release pinned by this site's generated package facts, in a throwaway Git repository drilled on 2026-08-29; identifiers, hashes, and transcripts are quoted from that recorded session, and running the same drill again mints fresh ones.
A definition precise enough to cite
Task memory is the repository-resident record of units of work, structured so that a process with zero prior context can recover the state of the work in one read and change that state only through a write that says what happened. Five properties do the qualifying, and an artifact missing any of them degrades into something weaker:
- It outlives the processes that use it. The record persists when the session, window, machine, or agent that produced it is gone. Memory that dies with its conversation is a transcript, not memory.
- It is addressable, not scrollable. Each unit of work is one record with an identifier, so recovery is a lookup — not a re-read of everything in the hope of finding the relevant part.
- It carries structure and account together. Status, dependencies, and commit pointers are fields a script can branch on; the free-form body and response carry intent and narrative a human can read. Either alone is half a memory.
- It is versioned with the work it describes. The record lives in the same repository and history as the code, so the memory of a change and the change itself travel together through clones, branches, and review.
- It is checkable. Integrity is verifiable by command, so trusting old memory does not require trusting that nothing was quietly edited.
The recorded drill exercised the definition end to end. A task was created with a goal and acceptance lines in its body, claimed by a session that then went silent mid-work — its claim response read "tests not started yet, next step is the unit test for the default path" — and finished later, from a different process, through the recovery arc below. Every command is printed exactly as it ran:
The middle command is the whole recovery story. Run from a process that had never seen the work before, get returned the goal, the acceptance lines, the in-flight claim quoting the dead session verbatim, the null commit field, and both timestamps — one record, no joins, no archaeology. Nothing about the producing session needed to exist. That is the standard this definition holds every candidate to.
It is not chat history
The most common impostor is the conversation itself. A session transcript is linear, unbounded, and process-shaped: it records how reasoning unfolded, including the detours an agent abandoned, and its value decays with every turn that buries the operative facts deeper. A task record is bounded, structured, and outcome-shaped: it states the ask, the current state, and the account of the last writer, and it is queryable by field. When the transcript is gone — closed window, expired retention, a different machine — the task record still answers. When the task record says a blocker resolved, the transcript's earlier uncertainty about it is irrelevant.
The two are complements, and each has an owner. Conversation continuity — resuming, branching, cloning, and handing off the *thread* — is its own discipline with its own guide; the session id is the durable handle for the conversation layer, and nothing here replaces it. The split is a clean one: the thread tells you how the agent reasoned; the task record tells you what the work now is. A resuming agent should read the second first, and reach for the first only when the why behind a recorded decision matters. Teams that conflate the two end up pasting transcripts into prompts as memory — paying context-window cost for facts a single get would have returned as fields.
It is not a vector store
The second impostor is newer: an embedding index over documents, retrieving by semantic similarity. Task memory under YYLO Ledger is deliberately nothing of the kind, and the difference is measurable. Retrieval is lexical and exact — filters match field values, and text search matches substrings, case-insensitively by the release's default search configuration. The recorded drill searched the claimed task's response plane for dialer, a word that appears in it: one hit, the right task. Searched for DIALER: the same hit. Searched for networking — a synonym a human would call closely related, and an embedding index would rank highly: No results found. That miss is not a defect; it is the design. Work-state memory must return what was written, not what is plausibly like what was written, because an agent resuming work from the record dialer should not be handed a different task that merely feels similar.
Determinism extends to the machinery underneath. There is exactly one index — a SQLite cache — and the release README binds its contract twice over: a "Rebuildable .juno_task/cache/kanban.sqlite3 index; canonical Markdown remains authoritative", and a cache that provides "indexed broad queries without becoming source of truth". The cache is acceleration, not memory; the corpus the memory *is* lives in the canonical task files. Semantic recall is a real technology with real uses — discovering related prior work across a large corpus is a legitimate job — but that job belongs to a derived index somebody deliberately built and can deliberately rebuild, never to the substrate an agent trusts for the state of its own work.
Freshness rules: one truth, two derived layers
A memory substrate needs an unambiguous answer to *which copy is current*, and the ledger's answer is a strict hierarchy of three layers. The canonical layer is the current task file — one Markdown record per task, the single source of truth for what the work is now. The audit layer is the per-task event history — hash-chained, appended by every mutation, opened only when you ask: it replays how the record reached its current state and is never the read path for state. The acceleration layer is the disposable cache. State flows from exactly one of these three, and it is the first.
The recorded drill broke the hierarchy on purpose: with the cache directory deleted outright, the very next list answered correctly from the canonical files — and quietly rebuilt the cache beside them. cache rebuild is the explicit form, answered by the drill with a receipt-shaped line — {"rebuilt_tasks": 2, "path": ".../.juno_task/cache/kanban.sqlite3"} — and the parser registers the command under five words that state the whole contract: "Manage disposable query cache". The same discipline keeps the write side honest: every mutation locks and rewrites the canonical task file, then refreshes the cache after the fact, so no write path can ever consult the index for truth.
Freshness on the canonical layer is carried by two mechanisms. Every mutation rewrites the record's last_modified field, and listings order by it: with both drill tasks completed, the recovered task — completed seconds after its sibling — led under --sort desc and trailed under --sort asc, the ordering flipping exactly with the flag. And the update command can carry a revision expectation — the record's content hash, surfaced as the after_sha256 of the latest history event — so a writer working from a stale read is refused instead of silently overwriting. The flag is update's alone: the refusal it raises is the shared-TODO failure anatomy's ground, and the guards the other transitions use instead — the required account, the readiness invariants — plus how the files themselves lock, are documented in the storage-format guide. The freshness rule this page adds is the agent-facing one: read the record, take its revision token from the history tail, and hand it to the guarded write — the memory defends itself against stale writers so the reader does not have to.
Scope rules: the memory ends at the repository
Where the memory reaches is as load-bearing as what it holds, and the rules are few and sharp. The memory is rooted in a repository: the CLI finds the board by searching upward from the working directory, so the drill's fresh process, started three directories below the repository root, recovered the same board with no configuration — the memory belongs to the work, not to the shell's location. When a process must reach a board from somewhere unrelated, the root is pinned explicitly; the environment help registers the exact form, "JUNO_TASK_ROOT=PATH Pin .juno_task directory to PATH (overrides PWD-based search)", and the drill used it to read the full board from a directory containing no board at all:
The refusal to guess is the other half of the rule. Run with no pin from a directory with no board, the CLI did not search the machine for something plausible — it reported No tasks found and initialized an empty board right there. A memory substrate that might silently attach to some other repository's state is worse than one that starts empty; the boundary is what makes the reads trustworthy. The same principle bounds multi-repository setups: reaching another project's board is an explicit, named registration — there is no implicit federation and no silent fallback onto a neighboring store. And within one repository, the split between canonical and derived state follows the same lines as freshness: the task files are shared through Git, while each linked worktree keeps its own disposable cache and locks, so concurrent agents never contend over derived state. The merge machinery that reconciles concurrent task-file edits across worktrees is laid out in the storage-format guide, which owns that surface end to end.
What the record holds — and what it deliberately does not
An honest memory states its own extent. The released documentation draws this boundary for YYLO Ledger in one sentence each way: "Today it owns task state, dependencies, responses, history, archives, and commit links" — and the neighboring facts, from architectural decisions through agent attempts to deployment and production outcomes, "are not all fields in the current task record"; they connect through other lifecycle evidence. A definition that claimed the ledger remembers *everything* about engineering work would be unfalsifiable and uncitable. This one claims a bounded, verifiable extent — intent, state, dependencies, accounts, and commit pointers — and every claim inside that extent is a command away from being checked against the record itself.
That boundedness is precisely what makes task memory safe to treat as memory, and it composes with the boundaries above rather than competing with them. The transcript layer explains the reasoning; the evidence layer — walked link by link in the task-evidence guide — proves the chain; the memory layer holds the current truth that both of those orbit. Install the CLI where your agents already work, put one task on the board with acceptance lines in its body, and kill the session on purpose: the next process that reads the board picks the work up mid-sentence, from fields, with no archaeology. That is the whole promise of task state as durable agent memory — not that the agent remembers, but that it never had to.