Wave Summary

Field Value
purpose make “nothing is happening” a safe, observable factory state; stop autonomous token use after sustained idle; make server-backed Beads identity and note linkage fail closed instead of disappearing
development window opened August 2, 2026; this entry records the opening checkpoint rather than a completed exit
baseline b8ca1294 on main
identity hardening branch beads-identity-ys-yes-zdry; 5 commits through 9708f916
branch change surface 19 files, 1,647 insertions, 56 deletions
triggering incidents an orphaned ALS feature note exposed two clones with a stale Beads guard token; a manual shutdown request exposed the absence of a deterministic idle-to-off transition
current operating state ALS and ALS-refinery are usable with 34 Beads issues each; eSPS is off; the hardening branch is not yet on main; automatic idle shutdown and message expiry remain open
exit condition identity safeguards merged and audited across the workspace fleet; sustained authoritative idle stops every autonomous service exactly once; factory mail is purged; an explicit restart begins with an empty message session

Wave 5 proved that Yesod could carry a real cross-language product slice to a merged result. Wave 6 begins with a less glamorous question: what should the factory do when there is no result left to produce?

An autonomous system can waste resources while appearing quiet. A propulsion loop can keep prompting agents, a dispatcher can keep reconsidering an empty or blocked queue, and old coordination messages can be mistaken for current intent after a restart. At the same time, machine-local state can look like ordinary source code and spread a bad identity to every clone.

The two failures share a boundary problem. Durable truth and disposable execution state were not separated sharply enough. Wave 6 makes that separation explicit: notes, Beads issues, commits, and audit events are durable; agent mail, sessions, leases, and clone-local guard tokens are not.

Idle Is a Derived State, Not an Empty Screen

On August 2 the operator disabled eSPS to stop further autonomous prompts. The service status showed off with no daemon PID. That was the correct immediate containment action, but it was not yet a factory-level idle protocol. Turning off propulsion alone does not prove that a runner, gate, merge, or local agent is not still working.

The open feature request ys-yes-6qs5 / yes-4pgc defines the stronger contract. An idle decision must be derived from authoritative state across:

  • live factory agents;
  • claimed and in-flight dispatch runs;
  • refinery gates and merges;
  • actionable queued work; and
  • a configurable grace period that spans normal gaps between steps.

Only sustained idle may trigger shutdown. The shutdown itself must be idempotent and must disable eSPS, factory roles, the mail broker, local dispatcher, refinery supervisor, and seat keeper. Active work blocks the transition. A status and dry-run surface must show the exact evidence behind the decision, and the audit record must be produced without spending another LLM call.

This is a cost-control feature, but it is also a correctness feature. “No work is visible to me” is not evidence that no work exists. The factory may go dark only after all of its ownership records agree.

Coordination Has a Lifetime

At the opening checkpoint, the catalog still held 1,914 factory mail rows. Those rows were useful coordination artifacts when they were written; they are not a durable knowledge base. Preserving them indefinitely makes a later session vulnerable to stale nudges, obsolete handoffs, and accidental revival of work that has already been resolved elsewhere.

Wave 6 therefore assigns each information surface a lifetime:

Surface Lifetime Reason
Yesod notes and topics durable operator intent, decisions, incidents, and reusable knowledge
Beads issues and dependencies durable executable work identity and dependency state
Git commits and gate evidence durable implementation and verification record
audit event for an idle shutdown durable explains why and when autonomous execution stopped
agent mail and message rows bounded and purgeable transient coordination, not a source of truth
agent sessions and leases process-scoped execution ownership that must not survive its owner
.beads/metadata.json clone-local guard token binding one checkout to one server database

Idle shutdown is the natural garbage-collection boundary. Once the factory has proven that no active work remains, it can wipe transient messages and stop the processes capable of consuming them. A later explicit start should recreate a clean session rather than replay the previous factory’s conversational debris.

The ALS Incident Exposed an Identity Boundary

The immediate Beads incident began when yesod tool als feature-request created note ys-als-qh64 but could not create its linked issue. The note was left without a Beads identity and was therefore invisible to the dispatcher. Diagnosis showed that both the main ALS clone and its refinery clone failed all bd operations with a project identity mismatch.

The server database was healthy and contained 33 issues. Its metadata._project_id was 705f983c-c8f7-4ba6-b975-60772bfd6c3f. Both clones instead carried the local token 2046f420-abb4-4503-a5e1-408413288ac4, an identity minted by a later bd init. The guard correctly refused the connection: accepting either side silently would have risked writing one project’s issues into another project’s database.

The disease was propagation, not the guard. .beads/metadata.json had been tracked in Git, untracked once, and then swept back into an unrelated feature commit after its ignore rule disappeared. A machine-local token became repository history and spread through ordinary pulls to every clone.

Recovery followed the authority boundary in the safe direction:

  1. query the server metadata and issue count first;
  2. establish that the populated server database is the source of truth;
  3. replace only the clone-local guard tokens;
  4. untrack and durably ignore the metadata file; and
  5. retry the missing note-to-Bead link.

The orphaned note became issue als-qwf, raising the database count to 34. Both ALS workspaces then returned to ok. No issue history was copied or reinitialized.

The Server Became Canonical

Bug report ys-yes-zdry / yes-vr8b produced a five-commit hardening branch. Its central rule is simple: for a server-mode workspace, the canonical project identity lives in the server database. A runner or provisioning path may seed an identity only when the database is genuinely empty. If a populated database has no _project_id, Yesod stops rather than inventing one.

The branch carries the rule through the whole lifecycle:

Boundary Safeguard
provisioning read the existing server identity; generate only for an empty database
runner worktree staging write the server’s identity into local metadata instead of calling uuid4()
diagnosis yesod beads doctor compares local and server IDs and reports tracked or unignored metadata
repair yesod beads repair-identity TOOL --from-server previews by default and writes only with --apply
source control root ignore rule, pre-commit rejection, CI rejection, and worker instructions keep metadata out of commits
missing linkage a PostgreSQL outbox leases and retries failed note-to-Bead creation with bounded backoff

The last safeguard closes the exact invisibility gap exposed by ALS. Note creation and outbox enrollment occur in one catalog transaction. A temporary Beads failure no longer turns an actionable request into an untracked orphan; runners retry the recorded failure, and successful linkage removes the outbox row.

The branch contains regression coverage for canonical identity resolution, safe repair, Git guards, runner staging, and outbox retry behavior. At this checkpoint it is pushed through 9708f916, but it is not yet part of main. That distinction matters: implemented on a branch is evidence of progress, not fleet protection.

One Populated Database Still Needs a Deliberate Migration

The SJBGTD workspace demonstrates why the new code fails closed. Its server database contains 151 issues but has no _project_id. There is no safe value for an automated repair command to guess. The local token may be correct, but it must first be proven against the long-lived workspace and every healthy clone.

The handoff plan requires quiescing writers, capturing server and clone evidence, taking a recoverable Dolt snapshot, establishing one canonical UUID, inserting it server-side through an authorized path, and only then repairing each clone from the server. Backup configuration is a separate least-privilege operation; broad remote-admin authority must not be granted to yesoduser merely to make bd dolt push succeed.

This is intentional friction. A repair tool is safe because it refuses the case in which the operator has not yet established the truth.

What Has Landed, and What Remains

Area Evidence at this checkpoint Required before wave exit
ALS recovery both clones use the server identity; the orphan note is linked as als-qwf; each reports 34 issues retain healthy identity after normal clone and refinery activity
identity implementation five commits on beads-identity-ys-yes-zdry through 9708f916 merge, deploy, and run the fleet audit under the released Yesod
Git boundary ALS metadata is untracked and ignored; branch adds hook, CI, and worker guards audit every registered repo and refinery clone for tracked metadata
linkage durability branch adds a leased outbox and runner retry path demonstrate recovery from a real transient failure after deployment
immediate cost containment eSPS is off with no daemon PID implement and prove whole-factory idle detection and idempotent shutdown
message lifecycle ephemeral-mail contract is recorded in ys-yes-6qs5 purge existing transient rows, enforce retention, and prove clean restart
SJBGTD 151 server issues remain reachable; migration plan is documented establish _project_id, align all clones, and complete a recoverable backup sync

The New Exit Criterion

Earlier waves made the factory capable of continuing after failures. Wave 6 adds the complementary capability: stopping cleanly when continuation has no value.

The wave is complete only when two proofs exist. First, every server-backed workspace must derive identity from a known database of record, while every clone-local guard stays outside Git and every failed note linkage remains recoverable. Second, an idle factory must be able to explain that it is idle, wait through a bounded grace period, stop every autonomous component exactly once, remove transient coordination messages, and remain quiet until a human explicitly starts a clean session.

The durable lesson is that autonomy needs an off-state as carefully designed as its run-state. A factory that cannot distinguish durable truth from transient coordination will either forget important work or preserve activity forever. The quiet factory does neither.