Open Files

What the Open Files activity is, when it appears, and what your two action buttons actually do.

When to use this

For the conceptual background — what an identity switch does and why open files block it — see Identity Switching.


Why it exists

When you switch sentient (or in some cases switch node), the IdentitySwitchService runs the §SP-8a Save → Teardown → Mount cascade. Teardown unmounts the encrypted volume. If a process inside the app still has an open file handle beneath that mount, the unmount either fails or — worse — succeeds while the open handle points at freed memory, risking SIGSEGV.

To prevent that, the service runs OpenFileTracker::filesUnder(mountPath) before Save. If the tracker reports any open handle beneath the affected mount, the service:

  1. Pauses the switch (no Save runs yet — your previous identity is still fully alive)
  2. Pushes OpenFilesActivity listing every tracked file
  3. Hands the decision to you

This is §SP-8c.2's "detection at switch time" — the per-subsystem dirty-flag probe of §SP-8b doesn't catch in-memory open handles, so a separate tracker is needed.


What you'll see

OpenFilesActivity is a table view, one row per open file. Columns:

Column What it shows
Owner The subsystem that opened the file (e.g. SentientVault, AddressBook, NodeStore, BlobCourier, an LLM cache, a user-opened media file).
Path The absolute path under the mount root. Usually correlates with the owner — e.g. ${hivecluster}/.octomy/sentient/vault.json for the vault.
Mode read or write. Write handles carry unsaved state; force-closing them is riskier.
Age How long the file has been open. Useful for spotting a stuck subsystem versus a fresh open.

The activity has two buttons.

Cancel switch

Pops the activity, abandons the in-flight switch, leaves you on your previous identity. Always safe. Pick this if you're not sure what's holding the hive open.

Force continue

Iterates every tracked entry and calls the owning subsystem's forceClose(path) callback. If the owner registered with a callback (the §SP-8c.4 contract), it gets a chance to flush its in-memory state to disk before its handle releases. If the owner registered without a callback (legacy code paths still being retrofitted under §OF-3), the handle releases at the OS level with no flush — anything dirty in that owner is lost.

After every entry is closed, the service proceeds with Save → Teardown → Mount.


When Force continue is safe

Situation Safe to force? Why
All rows are read mode Yes No unsaved state to lose.
All rows belong to SentientVault, AddressBook, KeyStore, SentientRegistry, HiveRegistry Yes These five are dirty-state subsystems that the Save phase has already arranged to flush; their force-close callbacks honour that.
A row is a user-opened media file in write mode No. The media editor's state could be lost. Switch to that editor first, save manually, then retry the identity switch.
A row is BlobCourier mid-transfer Probably no. The transfer aborts. Wait for it to complete (it shouldn't take long), then retry the switch.
A row is a long-running OPAL session (model call, tool call) Probably no. The session loses its working state. Cancel the session first if you can.

When in doubt, Cancel switch and resolve the open handles manually, then retry.


Reach it as a diagnostic

OpenFilesActivity also runs in a diagnostic mode — same table, different two buttons — when reached from the Hive Lobby's Open files entry. This lets you inspect the tracker without an in-flight switch:

Use this when something feels wrong and you want to see what the app is holding open right now.


Troubleshooting

The activity shows a row but I have nothing visible open. A subsystem that opens files at startup may register without you knowing. Common culprits: the audit DB (opal-history.db), discovery's cache, courier blob writers from a recent transfer. The row is normal; pick Force continue if all rows are read-only.

The activity shows an empty list but the switch still pauses. Shouldn't happen — file a bug. The probe runs after a Save-pending check, so a non-empty result is the only thing that should push this activity.

Force continue completed but the next switch still surfaces the same row. The owner's forceClose callback didn't actually release the handle. File a bug with the owner subsystem name; the §SP-8c.4 contract requires release-on-callback.


Topic Why it's relevant
Active Mounts What hives are currently mounted — the mount paths the tracker filters against
Switch Sentient The user-facing flow that triggers Open Files
Identity Switching The six-phase switch and where Open Files fits in