Download src/continuity/inode_state.py from Snapkitty/sovereign-engine-v2: direct link, hf CLI and curl.
- Browser
- Download file 10.6 kB
-
https://huggingface.co/Snapkitty/sovereign-engine-v2/resolve/main/src/continuity/inode_state.py
- Command line
-
hf download hf://Snapkitty/sovereign-engine-v2/src/continuity/inode_state.py
-
curl -L -o inode_state.py https://huggingface.co/Snapkitty/sovereign-engine-v2/resolve/main/src/continuity/inode_state.py
10.6 kB
| """ | |
| Paradigm 3: Filesystem Inode State (Zero-Byte File Gates) | |
| Part of SOVEREIGN PYTHON LLM ENGINE | |
| Boolean state flags stored as directory entries. | |
| File existence = 1, absence = 0. | |
| No file content ever written or read β pure stat() calls. | |
| Structure: | |
| {base_dir}/ | |
| {agent_id}/ | |
| flags/ | |
| IDLE β exists = agent is idle | |
| THINKING β exists = agent is thinking | |
| ACTING β exists = agent is acting | |
| OBSERVING β exists = agent is observing | |
| REFLECTING β exists = agent is reflecting | |
| DONE β exists = agent is done | |
| ERROR β exists = agent errored | |
| step/ | |
| 0000000000000005 β filename = current step number (zero-padded) | |
| locks/ | |
| tool:filesystem.read β exists = this tool is checked out | |
| Why this is fast: | |
| - os.stat() is a single kernel syscall | |
| - Directory entries live in kernel dcache (hot in memory) | |
| - No open(), read(), write(), close() β just stat() + mkdir() + unlink() | |
| - Concurrent readers are safe (no file locking needed for boolean flags) | |
| - Corruption-proof: filesystem guarantees atomic rename/unlink | |
| Use cases: | |
| - Agent state machine flags (7 states) | |
| - Tool checkout tracking (which tools are in use) | |
| - Mutex locks (file existence = lock held) | |
| - Rate limit gates (file mtime = last call timestamp) | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import time | |
| from pathlib import Path | |
| from typing import Iterator | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Inode State Gate | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| class InodeGate: | |
| """ | |
| Single boolean state gate backed by a zero-byte file. | |
| set() β touch file (create if not exists) | |
| clear() β unlink file (delete if exists) | |
| get() β stat file (True if exists) | |
| mtime() β file modification time (useful for rate limiting) | |
| """ | |
| def __init__(self, path: Path): | |
| self.path = path | |
| self.path.parent.mkdir(parents=True, exist_ok=True) | |
| def set(self) -> None: | |
| self.path.touch(exist_ok=True) | |
| def clear(self) -> None: | |
| try: | |
| self.path.unlink() | |
| except FileNotFoundError: | |
| pass | |
| def get(self) -> bool: | |
| return self.path.exists() | |
| def toggle(self) -> bool: | |
| if self.get(): | |
| self.clear() | |
| return False | |
| else: | |
| self.set() | |
| return True | |
| def mtime(self) -> float | None: | |
| try: | |
| return self.path.stat().st_mtime | |
| except FileNotFoundError: | |
| return None | |
| def age_seconds(self) -> float | None: | |
| mt = self.mtime() | |
| return (time.time() - mt) if mt is not None else None | |
| def __bool__(self) -> bool: | |
| return self.get() | |
| def __repr__(self) -> str: | |
| return f"InodeGate({self.path.name}={'1' if self.get() else '0'})" | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Inode State Machine | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Standard agent state flags | |
| AGENT_FLAGS = [ | |
| "IDLE", "THINKING", "ACTING", "OBSERVING", | |
| "REFLECTING", "DONE", "ERROR" | |
| ] | |
| class InodeStateMachine: | |
| """ | |
| Agent state machine using zero-byte files as boolean flags. | |
| State transitions are atomic at the filesystem level: | |
| transition(remove={"THINKING"}, add={"ACTING"}) uses | |
| a rename-based swap to avoid intermediate invalid states. | |
| Directory structure: | |
| {base}/{agent_id}/flags/IDLE | |
| {base}/{agent_id}/flags/THINKING | |
| ... | |
| {base}/{agent_id}/step/{zero_padded_step} | |
| {base}/{agent_id}/locks/{lock_name} | |
| Usage: | |
| ism = InodeStateMachine(base_dir, agent_id="react_1") | |
| ism.transition(remove={"IDLE"}, add={"THINKING"}) | |
| ism.set_step(1) | |
| print(ism.active_flags()) # ["THINKING"] | |
| """ | |
| def __init__(self, base_dir: Path, agent_id: str): | |
| self.agent_id = agent_id | |
| self._root = base_dir / agent_id | |
| self._flags = self._root / "flags" | |
| self._step_dir = self._root / "step" | |
| self._locks = self._root / "locks" | |
| # Create directory structure | |
| for d in (self._flags, self._step_dir, self._locks): | |
| d.mkdir(parents=True, exist_ok=True) | |
| # Initialize to IDLE if no flags set | |
| if not any(True for _ in self._flags.iterdir()): | |
| (self._flags / "IDLE").touch() | |
| # ββ Flags ββββββββββββββββββββββββββββββββββ | |
| def set_flag(self, flag: str) -> None: | |
| (self._flags / flag.upper()).touch(exist_ok=True) | |
| def clear_flag(self, flag: str) -> None: | |
| try: | |
| (self._flags / flag.upper()).unlink() | |
| except FileNotFoundError: | |
| pass | |
| def has_flag(self, flag: str) -> bool: | |
| return (self._flags / flag.upper()).exists() | |
| def active_flags(self) -> list[str]: | |
| return sorted(p.name for p in self._flags.iterdir() if p.is_file()) | |
| def transition(self, remove: set[str], add: set[str]) -> None: | |
| """ | |
| Atomic-ish transition: clear old flags, set new flags. | |
| Uses individual unlink/touch β not a true atomic swap, | |
| but fast enough for single-process agents. | |
| For true atomicity, use rename-based swap (future extension). | |
| """ | |
| for flag in remove: | |
| self.clear_flag(flag) | |
| for flag in add: | |
| self.set_flag(flag) | |
| def clear_all(self) -> None: | |
| for p in self._flags.iterdir(): | |
| if p.is_file(): | |
| p.unlink() | |
| # ββ Step counter βββββββββββββββββββββββββββ | |
| def set_step(self, step: int) -> None: | |
| """Store current step as filename (zero-padded 16 digits).""" | |
| # Remove old step files | |
| for p in self._step_dir.iterdir(): | |
| if p.is_file(): | |
| p.unlink() | |
| # Create new step file | |
| (self._step_dir / f"{step:016d}").touch() | |
| def get_step(self) -> int: | |
| """Read current step from directory entry.""" | |
| files = sorted(p.name for p in self._step_dir.iterdir() if p.is_file()) | |
| if not files: | |
| return 0 | |
| return int(files[-1]) | |
| # ββ Locks ββββββββββββββββββββββββββββββββββ | |
| def acquire_lock(self, lock_name: str) -> bool: | |
| """ | |
| Try to acquire a named lock. | |
| Returns True if acquired, False if already held. | |
| Uses exclusive creation (O_CREAT | O_EXCL at filesystem level). | |
| """ | |
| lock_path = self._locks / lock_name.replace('/', '_').replace(':', '-') | |
| try: | |
| fd = os.open(str(lock_path), os.O_CREAT | os.O_EXCL | os.O_WRONLY) | |
| os.close(fd) | |
| return True | |
| except FileExistsError: | |
| return False | |
| def release_lock(self, lock_name: str) -> None: | |
| lock_path = self._locks / lock_name.replace('/', '_').replace(':', '-') | |
| try: | |
| lock_path.unlink() | |
| except FileNotFoundError: | |
| pass | |
| def held_locks(self) -> list[str]: | |
| return [p.name for p in self._locks.iterdir() if p.is_file()] | |
| # ββ Rate limiting via mtime βββββββββββββββββ | |
| def rate_gate(self, gate_name: str, min_interval_s: float) -> bool: | |
| """ | |
| Rate limit gate using file mtime. | |
| Returns True if allowed (enough time elapsed), False if rate-limited. | |
| Touching the gate file resets the timer. | |
| """ | |
| gate = InodeGate(self._locks / f"rate_{gate_name}") | |
| age = gate.age_seconds() | |
| if age is None or age >= min_interval_s: | |
| gate.set() # reset timer | |
| return True # allowed | |
| return False # rate limited | |
| # ββ Introspection ββββββββββββββββββββββββββ | |
| def snapshot(self) -> dict: | |
| return { | |
| "agent_id": self.agent_id, | |
| "active_flags": self.active_flags(), | |
| "step": self.get_step(), | |
| "held_locks": self.held_locks(), | |
| } | |
| def destroy(self) -> None: | |
| """Remove all inode state for this agent.""" | |
| import shutil | |
| shutil.rmtree(self._root, ignore_errors=True) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Multi-agent inode registry | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| class InodeRegistry: | |
| """ | |
| Registry of all active agents tracked via inode state. | |
| Scan base_dir to discover all agents without any central index. | |
| The directory listing IS the index. | |
| """ | |
| def __init__(self, base_dir: Path): | |
| self.base_dir = base_dir | |
| base_dir.mkdir(parents=True, exist_ok=True) | |
| def get_agent(self, agent_id: str) -> InodeStateMachine: | |
| return InodeStateMachine(self.base_dir, agent_id) | |
| def list_agents(self) -> list[str]: | |
| return [ | |
| d.name for d in self.base_dir.iterdir() | |
| if d.is_dir() and (d / "flags").exists() | |
| ] | |
| def all_snapshots(self) -> list[dict]: | |
| snapshots = [] | |
| for agent_id in self.list_agents(): | |
| ism = self.get_agent(agent_id) | |
| snapshots.append(ism.snapshot()) | |
| return snapshots | |
| def active_agents(self) -> list[str]: | |
| """Agents that are not IDLE and not DONE.""" | |
| result = [] | |
| for agent_id in self.list_agents(): | |
| ism = self.get_agent(agent_id) | |
| flags = set(ism.active_flags()) | |
| if flags and not flags.issubset({"IDLE", "DONE"}): | |
| result.append(agent_id) | |
| return result | |