Skip to content

Fence CLI and Bot stale lease recovery - #499

Merged
sambitcreate merged 15 commits into
mainfrom
feature/lease-reclaim-fencing
Oct 16, 2026
Merged

sambitcreate merged 15 commits into
mainfrom
feature/lease-reclaim-fencing

Conversation

@sambitcreate

@sambitcreate sambitcreate commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Closes #405 and #392.

Change

  • Use a permanent, private *.lease.lock guard for CLI leases and Bot profiles. A small native helper takes an OS flock on an inherited file descriptor; the parent keeps that open description through the lease. A raw read/open/close of the guard cannot drop the lock, and a process crash releases it.
  • Keep owner JSON as diagnostic metadata. New records carry protocol: "flock-v1"; a free guard permits recovery even if the recorded PID has been reused. Malformed JSON values, including null, are reclaimable. Live legacy records stay protected unless the PID is verifiably foreign.
  • Put stale serve metadata and socket cleanup under the same guard. Foreground serve, status, daemon start, and stop recover stale records before trusting a PID.
  • Serialize Bot opens behind closes so an open cannot return a harness undergoing teardown. A failed close keeps the entry unavailable until teardown succeeds. Shutdown closes mutation admission, drains admitted operations and harnesses, then releases the profile guard.
  • Ship the helper in standalone CLI bundles and macOS/Linux desktop packages, with prebuilt universal macOS and x64/arm64 Linux binaries, signing rules, and package verification. Both runtime and renderer CI lanes stage the helper before Bot tests.

Behavioral checks

  • CLI: forced stale-removal interleaving, same-process reacquire after a raw guard read, recycled live PID recovery, malformed null owner recovery, foreground serve with a legacy recycled foreign PID, and serve cleanup racing a replacement owner.
  • Bot: three ready contenders after SIGKILL, SIGSTOP holder with missing metadata, raw guard read, unsafe guard rejection, recycled PID recovery, overlapping close/open, failed-close retry and guard retention, and shutdown draining an in-flight inspection.
  • Local: npm --prefix packages/cli test (106/106), npm run test:bot-runtime (207/207), npm run test:bots (824/824), npm run test:ci-policy (63/63), Telegram Bot reply outbox (14/14), Bot routines (9/9), root and CLI type checks, scoped ESLint, CLI and Electron builds, git diff --check. Package/signing/native helper tests (54/54) passed on the prior commit; the follow-up changes do not touch their implementation.
  • Linux x64 and arm64 container builds and direct contention/read smoke passed with the checked-in prebuilts. A packaged signed Electron app remains for hosted CI/release verification.

CI observation

The renderer-other job on commit 312f830eb failed four Telegram Bot tests because that lane had not built aiden-lease-flock (spawnSync ... ENOENT); the lane prerequisite is now added and the focused suite passes locally. The same job reported renderer/main/bots/bot-routines.test.tsx killed by SIGKILL after 92.2 seconds in the large shard, with no cause in the job log. Its standalone local run passed 9/9. This remains a possible flaky or resource failure for exact-head CI to classify; no timeout or retry behavior was changed.

Upgrade boundary

Stop older CLI processes, daemons, and Bot hosts before upgrading a shared directory or profile. Older binaries do not honor this guard, so mixed-version exclusion is not established. Guard files must remain in place on a local filesystem with working OS locks.

iOS baseline failure and merged fix

The iOS job on pre-merge head 33f5954c7 failed AidenBotChatActivityTests.testAPickMadeWhileASaveTimedOutGoesOutOnceTheRefreshShowsThatSaveLanded(). This matched the timeout/cancellation ordering defect fixed in PR #498 at a4366f62: publish the timeout before cancelling work. That fix reached main in 6bc994a5 and is now included in this PR by merge commit 82236f7b2. The old iOS job was not rerun. A simulator clone later reported NSMachErrorDomain -308 and xcodebuild exited 65; the log does not establish whether that simulator error was caused by the test failure.

Validation after merging main

  • The previously failing XCTest passed 1/1 on a local iPhone 17 Pro simulator (iOS 27.0), confirmed from the xcresult summary.
  • npm --prefix packages/cli test 106/106; npm run test:bot-runtime 207/207; npm run test:bots 824/824; npm run test:ci-policy 63/63; Telegram Bot reply outbox and Remote protocol 51/51; package/signing/native helper tests 54/54.
  • Root and CLI type checks, scoped ESLint, CLI and Electron builds, git diff --check passed. The root test chain contains all scripts and test files from both merge parents; the Remote contract remains revision 32 across server and fixture.
  • That validation was for the earlier head 82236f7b2; fresh required CI and review are needed after the next main integration.

E2E baseline failure fixed on main

The exact-head Electron E2E shard 3 job on 82236f7b2 reported 90 passed, 1 skipped, and 1 flaky. The sole failing attempt was tests/e2e/draft-agent-chats.spec.ts:205: at line 226 the workspace plus button's opacity was expected to be 0 but remained 1; Playwright's retry passed, while --fail-on-flaky-tests kept the job red. The row's expand control retained focus after the pointer moved away, so the focused-row action remained visible. PR #506 corrected that baseline test expectation without changing renderer behavior and merged to main at 896f31ae. This job was not rerun and no E2E code was changed in #499. PR #501 merged to main at b1e6054a. Its changes and the #506 baseline E2E repair were integrated into #499 by merge commit cd5781fce. The prior flaky job remains documented here; fresh exact-head CI must establish the current result. PR #504 then merged to main at ee218d1f and was integrated into #499 by merge commit d0ed5498b.

Validation after integrating #501 and #506

  • The three native-helper manifest conflicts were resolved from the checked-in binaries and current source hashes, retaining both the lease-flock and updated subagent-file-mutator entries. Native-helper and package/signing tests passed 34/34.
  • Local Bot runtime 207/207, Bots 824/824, CLI 106/106, CI policy 63/63, native mutator 30 passed with 3 platform skips, root and CLI type checks, and scoped ESLint passed. The root test scripts retain the entries from both merge parents.
  • Coding-tools and Telegram Bot reply outbox passed 76/76 under CI-pinned Node 22.22.3. The same local command under Node 26.10.0 failed the older native-glob comparison test at main/services/coding-tools.test.ts:2396 because fs.glob("**/*") omitted safe symlink descendants that Aiden returned; rerunning with the pinned CI Node passed.
  • That integration head was cd5781fce; its hosted CI results are below.

Hosted CI observation on prior head (cd5781fce)

  • Runtime/subagents job failed 1 of 3,456 tests: main/services/bot-runtime/live-projection.test.ts:1429, “while classifying fails, a cached routine stays hidden and the person's classified message stays listed; the new one waits, then appears.” Its timing assertion at line 1452 expected the first-to-third classification retries to span at least 295 ms, but saw 3 calls sooner. This file is unchanged by Fence CLI and Bot stale lease recovery #499; the focused Bot runtime suite passed locally 207/207. The workflow completed with this failure. This head was superseded by the Prevent parent write_file symlink-retarget writes #504 integration, so no stale-head rerun was started. The flaky failure remains a bug even if that rerun passes; no timeout, retry, or assertion has been weakened.
  • Linux x64 job failed its deterministic Electron E2E gate under --fail-on-flaky-tests: 210 passed, 9 skipped, 1 flaky. The first attempt of tests/e2e/settings-model-picker.spec.ts:104 timed out at line 267 waiting for one [cmdk-item] after opening the List tab (expected 1, received 0); its Playwright retry passed. The test is unchanged by Fence CLI and Bot stale lease recovery #499. The workflow completed with this failure; the superseding Prevent parent write_file symlink-retarget writes #504 integration will receive a full new CI run. The flaky result remains documented.
  • Scope check: git diff origin/main...cd5781fce contains neither failed spec, the Bot live-projection classifier, nor the renderer model-picker/settings implementation. The model-picker failure occurs on reopening its List tab after an unsuccessful search; no direct lease-helper call is in that flow. The Linux log also reports Bot/Telegram restore warnings, but it does not establish a causal link to the missing picker row.
  • All three desktop Electron E2E shards, iOS, Android, Linux arm64, desktop build, type/lint, and the remaining desktop regression shards passed. Linux x64/arm64 aggregate gates failed only because they consume the failed Linux x64 build result. Pullfrog and Hermes finished without new findings, with no unresolved review threads.

Validation after integrating #504

  • Prevent parent write_file symlink-retarget writes #504 reached main at ee218d1f; merged it into Fence CLI and Bot stale lease recovery #499 without rebase or force-push. The merge commit is d0ed5498bc82a16d79adc1ffb3ee5446ba883b71. The three generated native manifests were regenerated from the checked-in binaries and current sources, preserving both lease-flock and Prevent parent write_file symlink-retarget writes #504’s updated subagent-file-mutator.
  • CI-pinned Node 22.22.3 local checks: Bot runtime 207/207; Bots 824/824; CLI 106/106 after rebuilding; coding tools and Telegram outbox 80/80; root and CLI type checks; scoped ESLint. CI policy 63/63, native mutator 31 passed with 3 platform skips, native helper and macOS signing/package tests 34/34, and git diff --check also passed locally.
  • The root test scripts retain all keys and pretest:serial, pretest:coverage, and test:subagents segments from both merge parents. Aiden Remote remains revision 32; Prevent parent write_file symlink-retarget writes #504 changed no Remote contract files.
  • On d0ed5498b, CI run 38852933846 was still active when Release Aiden Agent 0.57.0 #507 advanced main. The runtime-subagents lane passed on that head after the earlier retry-timing failure. Pullfrog passed with no unresolved threads. Hermes failed during its engine before a verdict, and the requested /hermes review follow-up failed the same way. Neither is a code finding or an accepted review verdict.

Validation after integrating #507

  • Release Aiden Agent 0.57.0 #507 advanced main to 515de6738 for release version 0.57.0. Merged it into Fence CLI and Bot stale lease recovery #499 as fbfac1c88 without rebase or force-push; there were no conflicts. The root test scripts and the three checked pretest:serial, pretest:coverage, and test:subagents values match both merge parents. Aiden Remote remains revision 32, unchanged by Release Aiden Agent 0.57.0 #507.

  • Under CI-pinned Node 22.22.3, local Bot runtime passed 207/207, Bots passed 824/824, CLI passed 106/106 after rebuilding, and root and CLI type checks passed. git diff --check passed.

  • Prior head fbfac1c88: exact-head CI run 38854202446 passed at 06:40 UTC; release-consumer contract run 38854202360 passed. The Linux x64 job passed its deterministic Electron E2E gate, including the model-picker suite that failed on Fence CLI and Bot stale lease recovery #499's prior head. Separately, #494's Linux x64 job reported the same missing [cmdk-item] symptom on both initial attempt and retry; this cross-PR result does not establish lease causation. Pullfrog passed and no review threads are unresolved. Hermes failed in its engine at 05:15 UTC after initialization (agy failed (3)) without a verdict. The single exact-head /hermes review retry was requested after a cooldown at 05:50 UTC and failed in the same engine phase by 05:51 UTC, again without a verdict. No further automatic Hermes retries are planned on this head absent concrete service-recovery evidence. The PR remains blocked on a real Hermes verdict.

  • At 06:13 UTC, Hermes posted another engine-phase failure on the same head without a new /hermes review comment; its status and updated comment still contain no verdict. iOS passed; desktop runtime-subagents and macOS E2E/build jobs remained pending. The review gate stays closed.

  • The exact-head required CI gates (CI required, Linux x64/arm64, and Fedora RPM) all passed. Hermes posted further same-head engine failures without new /hermes review comments, most recently at 09:59 UTC in its updated failure comment; it still has no verdict.

  • Read-only Hermes service-log investigation found AGY RESOURCE_EXHAUSTED (429): Individual quota reached across review sessions from 04:43–10:36 UTC. The reported quota reset is approximately 15:34 UTC (11:34 a.m. EDT) on October 16. Hermes is using its persisted backoff; the public PR comment exposes only agy failed (3). No further manual review trigger is planned before the reset, and a real exact-head review verdict remains required.

Validation after integrating #508, #509, #510, #511, and #512

  • Main advanced through #508, #509, #510, #511, and #512 to 264b537a. Merged main into Fence CLI and Bot stale lease recovery #499 without rebase or force-push; the resulting commit is 9df88d34c6bb170c4be13e484d9a53ba2fae8614. There were no conflicts. The root package test scripts retained all keys and the pretest:serial, pretest:coverage, and test:subagents values from both merge parents. Remote revision 33, its fixture, and iOS assertion agree; Android’s revision floor remains compatible.
  • Under CI-pinned Node 22.22.3, the Aiden Remote suite, rebuilt CLI suite (106/106), Bots (826/826), command-system (103/103), CI policy (63/63), root and CLI type checks, E2E type check, and production build passed. The Fix flaky Simulator stream E2E that blocked the 0.57.0 release #508 Simulator stream E2E spec passed locally (1/1). The Hide focus rings when using the mouse, keep them for keyboard navigation #511 focus-navigation assertion passed in its containing E2E test. Android AidenRemoteClientTest and AidenBotContractTest passed. On an iPhone 18 Pro simulator (iOS 27.0), AidenBotSessionAttachmentTests, AidenBotActivityContractTests, and the Remote fixture test passed 19/19 with zero skips; this is simulator verification, not physical-device acceptance. git diff --check passed.
  • The full local chat-shell-interactions.spec.ts run had 24 passes and one failure in the unchanged “highlighted menu rows keep readable content and destructive rows stay red” test: after hovering Recent, its background remained transparent instead of settling on the accent fill within 10 seconds. A single isolated rerun of that exact test passed. This remains a flaky test; no timeout, retry, or assertion was weakened, and no lease causation is established.
  • On now-stale head 9df88d34, Electron E2E shard 3 in run 38950674852 failed under --fail-on-flaky-tests: 90 passed, 1 skipped, 1 flaky. The first attempt of tests/e2e/chat-top-bar.spec.ts:327, “Retry chosen after leaving a failed worktree send creates the worktree and starts the reply,” could not find [data-worktree-send-failure] at line 350 within 20 seconds after Enter. Playwright retry passed. The failure attachment showed only “Checking simulator setup…” and “Start Live” notices plus unrelated Bot/Telegram restore warnings; it does not show whether the send reached worktree creation. At the time of that failed run, neither the spec nor its renderer flow had been changed by Fence CLI and Bot stale lease recovery #499. This flaky result remains a bug even though the retry passed; no timeout, retry, or assertion was weakened. The workflow is terminal with this as its sole test failure; the dependent CI required gate failed. The branch was behind main after Fence Device Hub restarts after stop #496, so this stale-head job was not rerun; the new head has fresh CI. PR #501’s earlier E2E shard 3 showed the same spec and missing failure notice on its first attempt, with a passing retry. After locally merging Fence Device Hub restarts after stop #496 into Fence CLI and Bot stale lease recovery #499, this focused spec passed 3/3 repeats without a Playwright retry. The available logs do not establish whether the failed attempts reached worktree creation; a product race remains unconfirmed.
  • On now-stale 9df88d34, CI run 38950674852 finished red only for the E2E shard 3 flake documented above; the release-consumer run, Pullfrog, and Hermes full review passed. No review threads were unresolved.

Validation after integrating #496 and the worktree-send readiness assertion

  • Fence Device Hub restarts after stop #496 reached main at 5661bae0. Merged it into Fence CLI and Bot stale lease recovery #499 without conflicts, rebase, or force-push as 4fc2044e6b70d39f14bce454c1702b81bb354216. Root test, pretest:serial, pretest:coverage, and test:subagents chains match both merge parents; every script key is retained, and the lease branch’s pretest:bots helper prerequisite remains. Remote contract revision 33 remains aligned across server, fixture, and iOS assertion.
  • Node 22 local checks after the merge: focused Device Hub/service tests 80/80, root type-check, production build, and the unchanged worktree-send E2E spec 3/3 repeated runs without a Playwright retry.
  • Prior pushed head 066cbb951ebfcfe0a485a2c5cee8a37b1fde4979 adds one E2E setup assertion: wait until the branch-name row visibly shows aiden/taken before closing the picker and sending. E2E type-check passed; that focused flow passed 5/5 repeated local runs without retry on this exact head. The pre-assertion flow also passed 3/3 locally, so local repetition alone does not prove the CI flake is fixed. No timeout, retry count, or --fail-on-flaky-tests policy changed.
  • On that prior head, CI run 38969198571 was later superseded and cancelled; release-consumer run 38969198589 and Pullfrog passed. Hermes finished a full exact-head review with confidence 5/5 and no findings. No review threads are unresolved. Required CI on that prior head did not complete.
  • On prior head 066cbb951, renderer-other job 117203214329 failed 1 of 3,552 tests: scripts/vendor-cua-driver.test.mjs:388, “bounded vendor commands kill descendants that retain an exited leader’s stdio.” At line 418 it got ENOENT reading the temporary descendant.pid file; the fixture’s child leader writes that file after spawning its descendant under a 250 ms bounded-command timeout. This source is unchanged by Fence CLI and Bot stale lease recovery #499. The focused test passed locally 1/1 on Node 22.22.3. The log does not establish a lease/product failure or which scheduling step missed the deadline. The workflow was superseded and cancelled after the next push. Linux x64/arm64 and CI required gates failed because their dependencies were cancelled; no further test failure was established. No stale-head rerun was started. Preserve this symptom and job link even if later CI passes.

Prior head and vendor-command fixture review

  • Prior pushed head f3a1fa24fb05cc6034f9aae9269a7e1f6170449d is a one-commit descendant of 066cbb951; main was 5661bae0 at that push. The commit changes only scripts/vendor-cua-driver.test.mjs. A local Node 22.22.3 run of the focused descendant-cleanup test passed 1/1, and git diff --check passed. No branch push was made from this monitoring chat.
  • The fixture now waits for a valid descendant PID before awaiting the bounded command's timeout, so the test continues to verify that a spawned descendant exits. It also raises the test command's timeout from 250 ms to 2,000 ms and its prompt-settlement ceiling from 1,500 ms to 3,500 ms. This follows the prior ENOENT CI flake. Pullfrog's unresolved P2 thread confirms that PID polling begins after runBoundedCommand() arms its deadline, leaving the startup race intact; the larger timeout conflicts with AGENTS.md's flaky-test rule. A passing run alone will not establish that the race is fixed; retain the prior failure record above. No production command timeout, retry count, or --fail-on-flaky-tests setting changed.
  • Exact-head CI run 38971094251 completed successfully on that prior head, including every required Linux and desktop gate. Release-consumer run 38971094269 passed; Pullfrog completed with the unresolved P2 finding above. Hermes completed a full exact-head review at 21:51 UTC with confidence 5/5 and no findings. The Pullfrog thread kept that head's review gate closed; the corrective commit and subsequent main merge require fresh exact-head checks and review.

Current head after #494 and #505

  • Pushed head 8586738e4c1e2e525b7a182610c8252bf836b620 contains corrective commit c64bbe87c and a merge of main 1575fda4f (Fix run_command cleanup after shell closes #494 process cleanup and Upgrade Pi to 1.3.0 in lockstep across the app and the CLI #505 Pi 1.3.0). The merge had no conflicts, rebase, or force-push. Root test, pretest:serial, pretest:coverage, and test:subagents chains match both parents; all script keys survived and the lease helper remains in pretest:bots. Remote revision 33 remains aligned in TS, the shared fixture, and iOS; Android's revision floor remains compatible.
  • The vendor-command timeout test now holds the parent test clock until a deliberately delayed descendant has installed its SIGTERM handler and written its own PID. It then advances the original 250 ms timeout and checks prompt rejection within the original 1,500 ms settlement bound and the descendant's exit. The prior ENOENT flake remains documented above. The product command timeout, retry count, and --fail-on-flaky-tests policy are unchanged. This addresses Pullfrog's prior P2 finding. Pullfrog's exact-head review confirmed the synchronized fixture readiness and original 250 ms/1,500 ms bounds with no new issues; the prior thread is resolved.
  • Under Node 22.22.3 after refreshing root and standalone CLI dependencies for Pi 1.3.0, local checks passed: CLI build/tests 106/106, Bot runtime 207/207, Bots 826/826, coding tools 67/67, Remote/catalog 139/139, vendor/OAuth 34/34, CI policy 63/63, command system 103/103, native/package/signing 42/42, root and CLI type checks, scoped ESLint, production build, and git diff --check. The full vendor suite also passed 31/31 before the merge. These are local results. Fresh exact-head CI 38978785667 is still running. Release-consumer 38978785671 passed. Pullfrog found no new issues on this head and the prior P2 thread is resolved. Hermes completed a full 5/5 exact-head review with no findings. CI remains the open gate.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Two lifecycle regressions need fixing before merge: reopening a closing Bot returns an unusable session, and foreground serve loses recycled-PID recovery. The new child fixture also fails the required lint check.

Reviewed changes: Reviewed the complete CLI and Bot lease-fencing change, including acquisition, stale recovery, teardown, and multiprocess tests.

  • Permanent SQLite guards: CLI leases and Bot profiles hold owner-private SQLite transactions, with canonical in-process reservations and guarded diagnostic metadata cleanup.
  • Daemon lifecycle: Serve cleanup checks ownership under the guard, startup probes the socket listener, and the child owns stale socket removal.
  • Bot teardown: Harness entries remain tracked until close succeeds, and shutdown retains the profile guard when teardown fails.
  • Behavioral coverage: Added contention, process-death, stopped-owner, damaged-guard, and replacement-owner tests, plus operational documentation.

Validation: CLI build, CLI type-check, all 102 CLI tests, and all 201 Bot runtime tests passed. Both behavioral findings were reproduced separately; scoped ESLint also reproduced the fixture error reported by CI. Packaged Electron was not exercised locally.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

Comment thread main/services/bot-runtime/harness-host.ts
Comment thread packages/cli/src/serve.ts
Comment thread main/services/bot-runtime/test-support/kill-harness.mjs

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

CLI lease recovery now crashes on null diagnostic metadata. The two previously reported lifecycle concerns remain open.

Reviewed changes: Reviewed the changes from 918c41de to 312f830e, with the complete current PR diff as context.

  • Replaced SQLite guards: Introduced native flock acquisition through an inherited descriptor retained by the parent process.
  • Distinguished new metadata: Added flock-v1 owner records and guard-authoritative recycled-PID recovery for CLI leases, Bot profiles, and daemon lifecycle commands.
  • Fenced Bot shutdown: Closed mutation admission synchronously and drained admitted operations before releasing profile ownership.
  • Integrated native distribution: Added verified prebuilts, CLI staging, desktop packaging, signing rules, and package verification.
  • Extended behavioral coverage: Added raw guard-read, recycled-PID, and shutdown-drain cases, and fixed the child fixture's timer declaration.

Validation: CLI build and type-check passed; 104 CLI tests, 205 Bot runtime tests, 62 CI-policy tests, and 33 helper/distribution tests passed. One platform-specific archive test was skipped. Scoped ESLint passed. Reproduced the new metadata failure and reconfirmed the two existing lifecycle findings; resolved the fixed lint thread. Packaged signed Electron was not exercised locally.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

Comment thread packages/cli/src/state.ts Outdated
@very-hermes-bot

very-hermes-bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Hermes Review Bot

Confidence: 5

Engine: agy/gemini-3.8-flash-high
Review mode: full
Head: 8586738e4c1e2e525b7a182610c8252bf836b620
Generated: 2026-10-16T23:01:40+00:00
Reviews: 1

Summary

Exclusive CLI leases and Bot runtime profiles are now fenced by permanent OS flock guards (*.lease.lock) held on inherited file descriptors via a lightweight native C helper (aiden-lease-flock), closing the stale lease reclamation race documented in #405. Owner metadata in owner.json is treated as diagnostic and stamped with protocol: "flock-v1", enabling immediate reclamation of dead processes without getting wedged by OS PID recycling. Bot harness lifecycle operations serialize opens behind in-flight closes, keep failed teardown entries unavailable, and drain admitted operations before releasing the profile guard upon shutdown. Maintainers should double-check that packaging manifests and native signing rules consistently include aiden-lease-flock across Darwin universal and Linux x64/arm64 targets.

Confidence Score: 5/5

Full end-to-end inspection completed: kernel flock open-file-description semantics, process lifetime lock security assertions (O_NOFOLLOW, permissions, UID checks, heldPaths), CLI/serve lease and socket recovery, Bot harness serialization/teardown retention, native manifests, and packaging/signing configurations were verified alongside the deterministic timer fix for descendant cleanup in scripts/vendor-cua-driver.test.mjs.

📁 Important Files Changed
  • native/lease-flock/main.c: Minimal native C helper that performs a non-blocking exclusive flock on inherited file descriptor 3 and exits, allowing the parent process to retain the open file description lock.
  • main/services/process-lifetime-lock.ts: Core helper that securely opens the guard path (O_CREAT | O_NOFOLLOW, mode 0600), validates file safety (regular file, nlink === 1, mode bits, and UID ownership), spawns the native helper, and returns an idempotent release callback.
  • packages/cli/src/state.ts: Acquires the OS guard prior to inspecting or modifying owner.json, safely reclaiming stale locks while respecting live legacy owners.
  • packages/cli/src/serve-lifecycle.ts: Integrates the lease guard into background daemon startup, status checks, stop signaling, and stale socket cleanup.
  • main/services/bot-runtime/profile-lock.ts: Migrates Bot profile locking to the OS guard pattern and safely retires legacy records while preventing duplicate acquisition in the same process.
  • main/services/bot-runtime/harness-host.ts: Implements operation admission (admit), per-Bot lifecycle serialization, failed teardown isolation (closing), and graceful shutdown draining.
  • scripts/vendor-cua-driver.test.mjs: Stabilizes bounded command descendant cleanup tests by using mocked timers to await descendant readiness before triggering timeouts.
  • Packaging & build scripts (package.json, scripts/build-lease-flock.mjs, scripts/native-helpers.mjs, scripts/verify-*.mjs, scripts/sign-macos.mjs, prebuilt/native/*): Configures compilation, checksum tracking, code signing entitlements, and package verification for aiden-lease-flock.

Findings

No findings.

Sequence Diagram

sequenceDiagram
  autonumber
  actor App as Aiden Process
  participant Guard as File Descriptor (OFD)
  participant Helper as aiden-lease-flock
  participant FS as File System

  App->>Guard: openSync(<file>.lease.lock, O_CREAT | O_NOFOLLOW, 0600)
  App->>Guard: fstatSync(fd) (verify regular file, nlink==1, 0600, UID match)
  App->>Helper: spawnSync(helper, stdio[3]=fd)
  Helper->>Guard: flock(3, LOCK_EX | LOCK_NB)
  Helper-->>App: exit code 0 (acquired) or 10 (contended)
  alt Acquired (code 0)
    Note over App,Guard: Parent retains open fd; OS flock stays active on OFD
    App->>FS: rmSync(stale lock dir / socket if present)
    App->>FS: atomicJson(owner.json, { protocol: "flock-v1", pid, token })
  else Contended (code 10)
    App->>Guard: closeSync(fd)
    App-->>App: Throw lease contention error
  end
Loading
[]

Last reviewed commit: 8586738e4c1e
Reviews (1) · Comment /hermes review to trigger a new review · /hermes review full for full re-review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes: Reviewed the changes from 312f830e to 33f5954c, using the complete current PR diff as context.

  • Serialized Bot reopening: Routed opens through the lifecycle queue, retried failed teardown before reuse, and checked entry identity before idle cleanup closes a session.
  • Restored foreground recovery: Reinstated guarded stale-lease recovery before foreground serve acquires ownership, including legacy metadata naming a recycled foreign PID.
  • Validated diagnostic metadata: Treated null and other non-object owner values as stale instead of crashing acquisition.
  • Staged CI prerequisites: Added the lease helper to the renderer-other lane and coverage for both Bot-consuming lanes.
  • Extended behavioral coverage: Added usable close/open overlap, failed-close retry and guard retention, null-owner recovery, and foreground startup tests.

Validation: All 106 CLI tests, 207 Bot runtime tests, 63 CI-policy tests, and 23 focused Telegram/renderer tests passed. CLI build, root and CLI type checks, scoped ESLint, and git diff --check passed. Packaged signed Electron was not exercised locally, and several exact-head hosted CI jobs remain pending.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@sambitcreate

Copy link
Copy Markdown
Owner Author

/hermes review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes: Reviewed the three new main integrations from fbfac1c8 to 9df88d34, with the complete current PR diff and prior feedback as context.

  • Integrated Remote authority fixes: Checked host-owner Bot Files admission, device-bound handles, revocation checks, and the corresponding CLI audience wiring.
  • Integrated Bot and focus updates: Checked Web Search grants and editor state, keyboard/pointer modality behavior, and preservation of the lease-helper CI prerequisites.
  • Integrated attachment contracts: Checked revision 33 Bot uploads, replay-safe attachment reservations, and native-client compatibility at the lease-runtime boundary.
  • Verified merge integrity: Confirmed all three commits exactly match Git's conflict-free automatic merge trees, with no manual changes to lease recovery or teardown.

Validation on 9df88d34: 207 Bot runtime tests, 107 focused Remote tests, 119 Bot authority/editor and input-modality tests, 63 CI-policy tests, and 53 helper/packaging tests passed; one platform-specific archive test was skipped. Root type-check and git diff --check passed. Standalone CLI bundle tests, native mobile execution, and signed packaged Electron were not rerun locally. Exact-head hosted CI remains in progress; this review does not establish merge readiness.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes: Reviewed 9df88d34..066cbb95, with the complete current PR diff and prior feedback as context.

  • Synchronized worktree Retry setup: Added an assertion that the explicit branch name is saved before Escape closes the menu, preserving the existing failure, Retry, worktree creation, and reply assertions without changing timeouts or retries.
  • Verified main integration: Confirmed the device-host lifecycle fixes from main match Git's automatic merge tree exactly, with no manual changes to lease recovery or Bot teardown.

Validation: All 85 focused draft-branch and device-host/service tests passed. E2E type-checking, scoped ESLint, Playwright collection of all 16 top-bar scenarios, and git diff --check passed. Electron execution was not rerun in this Linux review environment. Exact-head hosted CI remains pending, so this review does not establish merge readiness.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The test-only follow-up widens a flaky startup deadline without synchronizing fixture readiness, contrary to the repository's flaky-test policy.

Reviewed changes: Reviewed 066cbb95..f3a1fa24, with the complete current PR diff and prior feedback as context.

  • Added PID-file polling: Started the timeout assertion concurrently, waited for a valid descendant PID, then awaited the command result and checked process exit.
  • Raised fixture deadlines: Increased the command timeout from 250 ms to 2 seconds and the elapsed-time ceiling from 1.5 to 3.5 seconds; production lease and command-runner code remained unchanged.

Validation: Scoped ESLint and git diff --check passed. The vendor suite passed 28/31 locally under Node v24.19.0; three descendant-exit checks failed with Process ... did not exit. One focused rerun confirmed that the changed scenario's descendant was already an unreaped zombie under sandbox PID 1, not a live escaped process. These local results do not establish a new process-cleanup regression or exact-head CI success.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

Comment thread scripts/vendor-cua-driver.test.mjs Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes: Reviewed f3a1fa24..8586738e, using the complete current PR diff and prior feedback as context.

  • Synchronized fixture readiness: Held the parent command clock until the delayed descendant installed its signal handler and published its PID, then exercised timeout cleanup with the original 250 ms deadline and 1.5-second settlement bound.
  • Preserved bounded verification: Kept readiness and process-exit polling on real timers and retained the descendant-exit assertion before final cleanup.
  • Verified main integration: Confirmed the merge containing process-cleanup updates and Pi 1.3.0 exactly matches Git's automatic merge tree, with no manual changes to lease recovery or Bot teardown.

Validation: All 207 Bot runtime tests and 63 CI-policy tests passed; scoped ESLint and git diff --check passed. The vendor suite passed 28/31 under sandbox Node v24.19.0, with three Process ... did not exit failures. One focused rerun confirmed the changed scenario's descendant was an unreaped zombie under sandbox PID 1, not a live escaped process; its timeout and prompt-settlement assertions completed successfully. Native mobile, Electron execution, and signed packaging were not rerun locally. Exact-head hosted CI remains incomplete, so this review does not establish merge readiness.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@sambitcreate
sambitcreate merged commit 6c2b44b into main Oct 16, 2026
27 checks passed
@sambitcreate
sambitcreate deleted the feature/lease-reclaim-fencing branch October 16, 2026 23:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P1: CLI stale-lease recovery permits two exclusive owners

2 participants