LearnNewsExamplesServices
Frontmatter
id16027
titleHeavy-maintenance lease defaults bypass the configured data root
stateClosed
labels
bugaicore
assigneesneo-gpt-emmy
createdAtJul 26, 2026, 10:36 PM
updatedAtJul 26, 2026, 11:42 PM
githubUrlhttps://github.com/neomjs/neo/issues/16027
authorneo-gpt-emmy
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 26, 2026, 11:42 PM

Heavy-maintenance lease defaults bypass the configured data root

neo-gpt-emmy
neo-gpt-emmy commented on Jul 26, 2026, 10:36 PM

Context

The operator approved PR #14205 on 2026-06-27 with an explicit follow-up request: the exported relative default .neo-ai-data/orchestrator-daemon/heavy-maintenance-lease.json ignores the configurable Agent OS data root and is an ADR-0019 trap. That follow-up was never filed.

The wider real-directory plane census in #15931 now makes the impact concrete. The orchestrator itself already resolves the lease beside its configured runtime state, but the reusable primitive, its singleton adapter, and seven operator-runnable scripts can still select the old cwd-relative path.

Verified at origin/dev 8412d22c08; none of the target files changed between 6e760e26ff and that head.

The Problem

AiConfig.orchestrator.dataDir is the declared, plane-member authority for orchestrator runtime state. MaintenanceBackpressureService.resolveHeavyMaintenanceLeasePath() correctly produces <dataDir>/heavy-maintenance-lease.json for orchestrated work.

The sibling manual path does not share that authority:

  • heavyMaintenanceLeasePrimitives.mjs exports a cwd-relative DEFAULT_HEAVY_MAINTENANCE_LEASE_PATH and propagates it through inspect/acquire/release/refresh defaults.
  • HeavyMaintenanceLeaseService repeats that default in both class config and JSDoc.
  • Seven config-aware scripts read AiConfig for the lease TTL but invoke the wrapper without leasePath.

A relocated real-directory seat or noncanonical deployment can therefore coordinate orchestrated work on <configured dataDir>/heavy-maintenance-lease.json while a manual or inherited-token child checks .neo-ai-data/orchestrator-daemon/heavy-maintenance-lease.json relative to its cwd. The inherited token then appears stale against the wrong file and the child can fall through to a second acquisition instead of inheriting the active lease.

The default /app layout can hide this: /app/.neo-ai-data/orchestrator-daemon and the cwd-relative default may coincide there. This ticket does not claim universal cloud breakage; it closes the split-path contract that appears when the declared root moves.

No-write falsifier:

  • configured path: /private/tmp/neo-parity-plane/orchestrator-daemon/heavy-maintenance-lease.json
  • primitive default: .neo-ai-data/orchestrator-daemon/heavy-maintenance-lease.json

The Architectural Reality

  • ai/configBase.mjs:674-687 declares orchestrator.dataDir and marks it planeMember: true.
  • ai/daemons/orchestrator/services/MaintenanceBackpressureService.mjs:167-180 is the correct sibling pattern: explicit override first, otherwise join the current data directory with heavy-maintenance-lease.json.
  • ai/daemons/orchestrator/services/heavyMaintenanceLeasePrimitives.mjs:5 owns the stale relative constant. Its defaults remain live at :184-190, :588-589, :632-636, :727-729, :774-777, :853-866, :961-969, and :1031-1040.
  • ai/daemons/orchestrator/services/HeavyMaintenanceLeaseService.mjs:45-55 repeats the stale default.
  • The seven callers that read AiConfig but omit leasePath are:
    • ai/scripts/lifecycle/backfill-memory-summaries.mjs:17,24-34
    • ai/scripts/maintenance/backup.mjs:15,621,717
    • ai/scripts/maintenance/defragChromaDB.mjs:9,1849-1852
    • ai/scripts/maintenance/ingestTenant.mjs:5,194-215
    • ai/scripts/maintenance/syncGithubWorkflow.mjs:2,88-91
    • ai/scripts/maintenance/syncKnowledgeBase.mjs:5,94-121
    • ai/scripts/runners/runSandman.mjs:2,105-121
  • test/playwright/unit/ai/scripts/maintenance/manualHeavyMaintenanceScriptLeaseAdoption.spec.mjs:42-74 covers only five of those seven scripts and verifies wrapper/owner/held behavior, not path authority.
  • learn/agentos/incidents/sandman-silent-failure-forensics.md:185-196 still tells operators to inspect the cwd-relative literal.

The Fix

  1. Replace the cwd-relative default with one shared path resolver whose inputs are an explicit override and the injected orchestrator dataDir. Keep the pure primitive config-free.
  2. Make pure lease operations fail loud before filesystem I/O when leasePath is absent; a hidden cwd fallback is no longer valid.
  3. Make HeavyMaintenanceLeaseService resolve its runtime default from the current AiConfig.orchestrator.dataDir at the use site, while preserving an explicit leasePath override.
  4. Pass the resolved configured path from all seven scripts at the wrapper call site.
  5. Expand the script-adoption census to all seven callers and require configured-root path wiring.
  6. Add a relocated-root inherited-token witness that proves parent and child inspect the same lease and never acquire a second file.
  7. Update JSDoc and the Sandman incident guidance to name the configured data directory rather than a cwd-relative literal.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
AiConfig.orchestrator.dataDir → heavy-maintenance lease resolver ADR-0019; ai/configBase.mjs:674-687 Resolve one absolute <dataDir>/heavy-maintenance-lease.json, with explicit override precedence Missing/invalid dataDir fails loud; never derive from cwd or process.env Resolver JSDoc Resolver unit tests for override, relocated root, and missing input
Pure inspect/acquire/release/refresh/wrapper operations Existing primitive surface in heavyMaintenanceLeasePrimitives.mjs Consume an explicit leasePath supplied by a config-aware boundary Missing path rejects before filesystem access Update parameter JSDoc and remove default claims Missing-path guard tests across the public operations
HeavyMaintenanceLeaseService Existing singleton adapter; ADR-0019 use-site rule Read the current AiConfig.orchestrator.dataDir at use time when no explicit override exists Explicit override wins; missing authority fails loud Correct leasePath_ JSDoc Service tests mutate the configured root and prove no module-load capture
Seven manual/script wrapper call sites #15931 consumer census; operator follow-up on PR #14205 Every caller passes the shared configured lease path alongside the existing TTL/owner metadata No cwd-relative fallback; held/error exit semantics remain unchanged Existing script JSDoc/comments where needed manualHeavyMaintenanceScriptLeaseAdoption.spec.mjs covers all seven and asserts path wiring
Sandman incident inspection guidance learn/agentos/incidents/sandman-silent-failure-forensics.md:185-196 Tell operators to inspect the lease under the configured orchestrator data directory Do not present the canonical default as universal Update incident guide Source assertion/grep plus docs review

Decision Record impact

aligned-with ADR 0019 — this removes an A1 re-derive/hidden-default path and restores AiConfig as the source of truth. It does not amend the ADR or add a new config leaf.

Acceptance Criteria

  • AC1 — no exported or internal cwd-relative heavy-maintenance lease default remains in the primitive/service path.
  • AC2 — pure lease operations require an explicit leasePath and fail loud before filesystem I/O when it is absent.
  • AC3 — the shared resolver gives an explicit override precedence and otherwise resolves <current AiConfig.orchestrator.dataDir>/heavy-maintenance-lease.json without module-load capture.
  • AC4 — all seven enumerated scripts pass that resolved path at their lease-wrapper call site.
  • AC5 — a relocated-root inherited-token test proves the child recognizes the parent lease and does not acquire a second file.
  • AC6 — the manual-script adoption spec covers all seven callers and fails if any caller omits configured-root path wiring.
  • AC7 — HeavyMaintenanceLeaseService JSDoc and Sandman incident guidance no longer advertise the cwd-relative literal as authority.
  • AC8 — focused unit tests pass without running Sandman, backup, sync, ingest, defrag, or backfill against live data.

Out of Scope

  • Direct orchestrator callers; they already use the configured resolver.
  • TenantRepoSyncService's dedicated sibling lease contract.
  • VectorService's path-free cooperative-yield predicate.
  • Adding another path/env leaf; AiConfig.orchestrator.dataDir already owns placement.
  • Running any heavy-maintenance script against the operator workstation as validation.
  • Closing #15931; this is one verified leaf in its full consumer census.

Avoided Traps

  • Keeping the relative default “for convenience.” That preserves the exact silent split the operator identified.
  • Reading process.env inside the primitive. The primitive must remain pure/config-free; the config-aware boundary injects placement.
  • Importing a backpressure service from every CLI. Path resolution belongs with the lease substrate, while the orchestrator adapter may delegate to it.
  • Claiming every cloud profile is broken. The canonical /app layout can coincide by accident; the falsifier is a moved root.
  • Testing by executing heavy jobs. Focused path/token tests prove the contract without risking live data.

Related

Origin Session ID: 27de6eb7-04ae-4eba-8b73-2b9f5eaf4dc3

Retrieval Hint: heavy maintenance lease path AiConfig orchestrator dataDir inherited token seven scripts #15931