LearnNewsExamplesServices
Frontmatter
id16514
titleFour lock/lease implementations own one concern across the ai daemons
stateOpen
labels
enhancementairefactoring
assigneesneo-opus-vega
createdAtAug 4, 2026, 10:41 PM
updatedAtAug 4, 2026, 11:17 PM
githubUrlhttps://github.com/neomjs/neo/issues/16514
authorneo-fable
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Four lock/lease implementations own one concern across the ai daemons

Open Backlog/active-chunk-12 enhancementairefactoring
neo-fable
neo-fable commented on Aug 4, 2026, 10:41 PM

Context

Operator-driven friction→gold from a values discussion (2026-08-04 evening): "models excel at spotting patterns. e.g. file writer lockings (canary) => do we use this in e.g. 3+ spots? would an own helper class win?" — measured on the spot, and the Rule of Three passed long ago. Live latest-open sweep at filing: latest 15 checked (#16495-#16513 window), no equivalent; #16488/#16495 own the SDK-boundary/marked-bridge concern, not lock/lease unification.

The Problem

Four separate implementations of the file-lock/lease concern live in ai/:

  • ai/daemons/embed/drainLock.mjs
  • ai/daemons/shared/fileLease.mjs
  • ai/daemons/wake/outboxLock.mjs
  • ai/daemons/orchestrator/services/heavyMaintenanceLeasePrimitives.mjs

plus ~12 further files carrying the pattern inline (grep -rlE "canary|lockFile|acquireLock" ai/ --include="*.mjs" → 16 files). Four owners of one concern means four falsifier sets, four witness suites, and four places for the next stale-lock/canary defect to hide — the class of bug that has repeatedly cost diagnosis time in the daemon family.

The Architectural Reality

  • ai/daemons/shared/fileLease.mjs is already positioned (by name and by home) as the natural absorber — the consolidation direction half-exists.
  • The four implementations predate each other across different daemon lanes (embed drain, wake outbox, orchestrator heavy-maintenance); their semantics need a comparison pass BEFORE unification: TTL/staleness handling, holder identity, release-on-crash behavior, and reentrancy differ in ways a naive merge would flatten. The comparison table is the first deliverable.
  • Deployment redline: the plane runs from this tree — consumers migrate in place, imports stay working at every commit, no directory moves in this ticket.

The Fix

  1. Comparison table of the four implementations' contracts (TTL, holder identity, crash-release, reentrancy, fsync/atomicity) — differences become explicit options on the unified helper, never silent flattenings.
  2. Absorb the other three into fileLease (or its successor shape if the table demands one), one consumer family per commit.
  3. One witness suite owning the unified contract (stale-lease takeover, crash-release, contention), replacing the per-copy coverage.

If the comparison table reveals genuinely incompatible semantics, the honest outcome may be TWO helpers (lock vs lease) — the ticket's success criterion is one owner PER CONCERN, not one file at any cost. Driver may split into a small epic if the consumer migration exceeds one reviewable PR; this ticket is the license.

Acceptance Criteria

  • The comparison table exists on this ticket before any code moves.
  • Every lock/lease call site in ai/ resolves to a shared helper; the absorbed modules are gone or are thin re-exports staged for removal.
  • The unified contract has a witness suite incl. stale-takeover and crash-release; per-copy duplicated tests retired.
  • No import breaks at any intermediate commit (deployment-safe migration).

Out of Scope

  • The SDK boundary / module-scope import class (#16488, #16495).
  • Any directory restructuring beyond the absorbed modules themselves.

Decision Record impact

none — consolidation within the landed daemon architecture.

Related

#16488, #16495 (adjacent boundary work — fold, don't duplicate), the ai-folder debt census ticket filed alongside this one.

Origin Session ID: 1913de09-6dc0-4d1e-a9a3-b51c33b46cdc

Retrieval Hint: query_raw_memories("four lock lease implementations fileLease drainLock outboxLock heavyMaintenanceLeasePrimitives rule of three")