You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: implement proactive roaming radar and network-throttled drift detection (#48)
Shifts remote divergence detection from reactive CLI polling to a proactive background daemon interrupt. The daemon now actively monitors the remote topology and fires OS-level notifications to prevent local entropy generation during distributed handoffs.
- Refactor `get_remote_drift_state` out of the CLI presentation layer and into `ops.py` for shared internal use.
- Implement atomic file I/O (`get_drift_state`, `set_drift_state`) using `os.replace` and `os.fsync` for cross-process state caching.
- Integrate a 15-minute throttled network fetch into the `daemon.py` core loop, gated by battery limits and TCP reachability.
- Add notification fatigue prevention by tracking the latest warned remote timestamp.
- Migrate and expand test coverage in `test_ops.py` and `test_daemon.py`.
- Update architecture documentation and Phase 2 roadmap.
Copy file name to clipboardExpand all lines: README.md
+44-23Lines changed: 44 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,8 @@
12
12
>
13
13
> **Git Pulsar decouples them. It is a background daemon that provides high-frequency, out-of-band state capture, ensuring your work is immutable and recoverable without polluting your project history.**
14
14
15
-
### 📡 The Mission: Decoupling Signal from Noise
15
+
## 📡 The Mission: Decoupling Signal from Noise
16
+
16
17
In a typical workflow, developers are forced to make "WIP" commits just to switch machines or save their progress. This introduces **entropy** into the commit log, requiring complex interactive rebases to clean up later.
17
18
18
19
**Git Pulsar** treats the working directory state as a continuous stream of data. It captures this "noise" in a dedicated namespace (`refs/heads/wip/...`), keeping your primary branch purely focused on "signal" (logical units of work).
@@ -28,21 +29,24 @@ In a typical workflow, developers are forced to make "WIP" commits just to switc
This system is designed to operate safely alongside standard Git commands without race conditions or index locking.
34
35
35
-
#### 1. Out-of-Band Indexing (The "Shadow" Index)
36
+
### 1. Out-of-Band Indexing (The "Shadow" Index)
37
+
36
38
Most autosave tools aggressively run `git add .`, which destroys the user's carefully staged partial commits.
37
39
***The Invariant:** The user's `.git/index` must never be touched by the daemon.
38
40
***The Implementation:** Pulsar sets the `GIT_INDEX_FILE` environment variable to a temporary location (`.git/pulsar_index`). It constructs the tree object using low-level plumbing commands (`git write-tree`), bypassing the porcelain entirely. This ensures **Zero-Interference** with your active workflow.
39
41
40
-
#### 2. Distributed State Reconciliation (The "Zipper" Graph)
42
+
### 2. Distributed State Reconciliation (The "Zipper" Graph)
43
+
41
44
In a distributed environment (Laptop ↔ Desktop), state drift is inevitable.
42
45
***The Mechanism:** Pulsar maintains a separate refspec for each machine ID.
43
46
***The Topology:** When you run `git pulsar finalize`, the engine performs an **Octopus Merge**, traversing the DAG (Directed Acyclic Graph) of all machine streams and squashing them into a single, clean commit on `main`.
***The Solution:** By decoupling commits from pushes, Pulsar can capture local state every few minutes while conserving battery by pushing to the remote at a lower frequency (e.g., hourly). This guarantees that the **Mean Time To Recovery (MTTR)** is minimized regardless of network availability or hardware failure.
48
52
@@ -52,20 +56,22 @@ In a distributed environment (Laptop ↔ Desktop), state drift is inevitable.
52
56
53
57
***Decoupled Cycles:** Independent intervals for local commits and remote pushes. Save your battery while staying protected.
54
58
***Smart Identity:** Automatically detects naming collisions with other devices on the remote, ensuring unique backup streams for every machine.
59
+
***Roaming Radar:** The background daemon actively polls for topological drift, firing a cross-platform OS notification if another machine leapfrogs your local session so you can `sync` before conflicts arise.
55
60
***Out-of-Band Indexing:** Backups are stored in a configured namespace (default: `refs/heads/wip/pulsar/...`). Your `git status`, `git branch`, and `git log` remain completely clean.
56
61
***Distributed Sessions:** Hop between machines. Pulsar tracks sessions per device and lets you `sync` to pick up exactly where you left off.
57
62
***State-Aware Diagnostics:** The `doctor` command correlates transient log events with active system health to prevent alert fatigue, and proactively scans for pipeline blockers like strict git hooks or broken `systemd` configurations.
58
63
***Zero-Interference:**
59
-
* Uses a temporary index so it never messes up your partial `git add`.
60
-
* Detects if you are rebasing or merging and waits for you to finish.
61
-
* Prevents accidental upload of large binaries (configurable threshold).
64
+
* Uses a temporary index so it never messes up your partial `git add`.
65
+
* Detects if you are rebasing or merging and waits for you to finish.
66
+
* Prevents accidental upload of large binaries (configurable threshold).
62
67
***Cascading Config:** Settings are merged from global defaults, `~/.config/git-pulsar/config.toml`, and local `pulsar.toml` or `pyproject.toml` files.
63
68
64
69
---
65
70
66
71
## 📦 Installation
67
72
68
73
### macOS
74
+
69
75
Install via Homebrew. This automatically manages the background service.
70
76
71
77
```bash
@@ -75,6 +81,7 @@ brew services start git-pulsar
75
81
```
76
82
77
83
### Linux / Generic
84
+
78
85
Install via `uv` (or `pipx`) and use the built-in service manager to register the systemd timer.
Pulsar is designed to feel like a native git command.
91
98
92
99
### 1. Initialize & Identify
100
+
93
101
Navigate to your project. The first time you run Pulsar, it will register the repo, **check for naming collisions**, and start the background protection loop.
94
102
95
103
```bash
@@ -99,15 +107,18 @@ git pulsar
99
107
*The daemon will now silently snapshot your work based on your configured intervals.*
100
108
101
109
### 2. Configure Your Intensity
110
+
102
111
Need high-frequency protection for a critical project? Set a preset or fine-tune the intervals in your project root.
103
112
104
-
**pulsar.toml**
113
+
#### pulsar.toml
114
+
105
115
```toml
106
116
[daemon]
107
117
preset = "paranoid"# 5min commits, 5min pushes
108
118
```
109
119
110
120
### 3. The "Session Handoff" (Sync)
121
+
111
122
You worked on your **Desktop** all night but forgot to push manually. You open your **Laptop** at class.
112
123
113
124
```bash
@@ -116,6 +127,7 @@ git pulsar sync
116
127
*Pulsar checks the remote, finds the newer session from `desktop`, and fast-forwards your working directory to match it.*
117
128
118
129
### 4. Restore a File
130
+
119
131
Mess up a script? Grab the version from your last shadow commit.
*Focus: Turning the tool from a blind script into a helpful partner that negotiates with you.*
221
240
222
-
-[ ]**Smart Restore:** Replace hard failures on "dirty" files with a negotiation menu (Overwrite / View Diff / Cancel).
223
-
-[ ]**Pre-Flight Checklists:** Display a summary table of incoming changes (machines, timestamps, file counts) before running destructive commands like `finalize`.
224
-
-[ ]**Active Doctor:** Upgrade `git pulsar doctor` to not just diagnose issues (like stopped daemons), but offer to auto-fix them interactively.
241
+
*[ ]**Smart Restore:** Replace hard failures on "dirty" files with a negotiation menu (Overwrite / View Diff / Cancel).
242
+
*[ ]**Pre-Flight Checklists:** Display a summary table of incoming changes (machines, timestamps, file counts) before running destructive commands like `finalize`.
243
+
*[ ]**Active Doctor:** Upgrade `git pulsar doctor` to not just diagnose issues (like stopped daemons), but offer to auto-fix them interactively.
-[x]**Roaming Radar:** Proactively detect if a different machine has pushed newer work to the same branch and notify the user to `sync`.
232
-
-[ ]**Decaying Retention:** Implement "Grandfather-Father-Son" pruning (keep all hourly backups for 24h, then daily summaries) to balance safety with disk space.
*[x]**Roaming Radar:** Proactively detect if a different machine has pushed newer work to the same branch and notify the user to `sync`.
251
+
*[ ]**Decaying Retention:** Implement "Grandfather-Father-Son" pruning (keep all hourly backups for 24h, then daily summaries) to balance safety with disk space.
233
252
234
253
### Phase 3: The "TUI" Experience (Visuals)
254
+
235
255
*Focus: Making the invisible backup history tangible and explorable.*
236
-
-[ ]**Time Machine UI:** A terminal-based visual browser for `git pulsar restore` that lets you scroll through file history and view side-by-side diffs.
237
-
-[ ]**Universal Bootstrap:** Expand `git pulsar --env` to support Linux (apt/dnf) environments alongside macOS.
256
+
*[ ]**Time Machine UI:** A terminal-based visual browser for `git pulsar restore` that lets you scroll through file history and view side-by-side diffs.
257
+
*[ ]**Universal Bootstrap:** Expand `git pulsar --env` to support Linux (apt/dnf) environments alongside macOS.
238
258
239
259
### Future Horizons
240
-
-[ ]**End-to-End Encryption:** Optional GPG encryption for shadow commits.
241
-
-[ ]**Windows Support:** Native support for PowerShell and Task Scheduler.
260
+
261
+
*[ ]**End-to-End Encryption:** Optional GPG encryption for shadow commits.
262
+
*[ ]**Windows Support:** Native support for PowerShell and Task Scheduler.
Copy file name to clipboardExpand all lines: src/README.md
+24-20Lines changed: 24 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,41 +5,45 @@ The `src/` directory contains the package source code. The architecture strictly
5
5
## Module Map
6
6
7
7
### 1. The Core Loop (State Management)
8
+
8
9
***`git_pulsar/daemon.py`**: The background process.
9
-
***Role:** The "Heartbeat." It wakes up, checks system constraints (Battery, CPU Load), and triggers the backup logic.
10
-
***Logic:** Decouples "Saving" (Commit) from "Publishing" (Push) using independent intervals to optimize for battery life.
11
-
***Safety:** Implements `GIT_INDEX_FILE` isolation to ensure it never locks or corrupts the user's active git index.
10
+
***Role:** The "Heartbeat." It wakes up, checks system constraints (Battery, CPU Load), and triggers the backup logic.
11
+
***Logic:** Decouples "Saving" (Commit) from "Publishing" (Push) using independent intervals to optimize for battery life. Incorporates the "Roaming Radar" to poll for remote drift asynchronously.
12
+
***Safety:** Implements `GIT_INDEX_FILE` isolation to ensure it never locks or corrupts the user's active git index.
12
13
***`git_pulsar/ops.py`**: High-level Business Logic.
13
-
***Role:** The "Controller." It orchestrates complex multi-step operations like `finalize` (Octopus Merges) and `restore`.
14
-
***Logic:** Calculates the "Zipper Graph" topology to merge shadow commits back into the main branch.
14
+
***Role:** The "Controller." It orchestrates complex multi-step operations like `finalize` (Octopus Merges), `restore`, and drift detection.
15
+
***Logic:** Calculates the "Zipper Graph" topology to merge shadow commits back into the main branch, and manages atomic file I/O for cross-process state tracking.
***Logic:** Implements a cascading hierarchy (Defaults → Global → Local) to merge settings from `~/.config/git-pulsar/config.toml` and project-level `pulsar.toml` or `pyproject.toml`.
17
+
***Role:** The "Source of Truth."
18
+
***Logic:** Implements a cascading hierarchy (Defaults → Global → Local) to merge settings from `~/.config/git-pulsar/config.toml` and project-level `pulsar.toml` or `pyproject.toml`.
18
19
19
20
### 2. The Abstraction Layer (Plumbing)
21
+
20
22
***`git_pulsar/git_wrapper.py`**: The Git Interface.
21
-
***Role:** A strict wrapper around `subprocess`.
22
-
***Philosophy:****No Porcelain.** This module primarily uses git *plumbing* commands (`write-tree`, `commit-tree`, `update-ref`) rather than user-facing commands (`commit`, `add`) to ensure deterministic behavior.
23
+
***Role:** A strict wrapper around `subprocess`.
24
+
***Philosophy:****No Porcelain.** This module primarily uses git *plumbing* commands (`write-tree`, `commit-tree`, `update-ref`) rather than user-facing commands (`commit`, `add`) to ensure deterministic behavior.
23
25
***`git_pulsar/system.py`**: OS Abstraction.
24
-
***Role:** Identity & Environment.
25
-
***Logic:** Handles the chaos of cross-platform identity (mapping `IOPlatformUUID` on macOS vs `/etc/machine-id` on Linux) to ensure stable "Roaming Profiles."
26
+
***Role:** Identity & Environment.
27
+
***Logic:** Handles the chaos of cross-platform identity (mapping `IOPlatformUUID` on macOS vs `/etc/machine-id` on Linux) to ensure stable "Roaming Profiles."
26
28
27
29
### 3. Service Management (Lifecycle)
30
+
28
31
***`git_pulsar/service.py`**: The Installation Engine.
29
-
***Role:** Interface with the host init system.
30
-
***Logic:** Generates and registers `systemd` user timers (Linux) or instructions for `launchd` (macOS/Homebrew).
32
+
***Role:** Interface with the host init system.
33
+
***Logic:** Generates and registers `systemd` user timers (Linux) or instructions for `launchd` (macOS/Homebrew).
31
34
32
35
### 4. The Interface
36
+
33
37
***`git_pulsar/cli.py`**: The User Entry Point & Diagnostic Engine.
34
-
***Role:** Argument parsing, UI rendering, and system health evaluation.
35
-
***Logic:** Uses `rich` for terminal visualization. Beyond routing subcommands to `ops.py` and `daemon.py`, it houses the `doctor`logic. It correlates repository state against transient event logs, detects topological drift across distributed sessions, and scans for host-environment pipeline blockers (e.g., strict git hooks, missing `systemd` linger).
38
+
***Role:** Argument parsing, UI rendering, and system health evaluation.
39
+
***Logic:** Uses `rich` for terminal visualization. Beyond routing subcommands to `ops.py` and `daemon.py`, it presents the `doctor`diagnostics. It correlates repository state against transient event logs, and relies on `ops.py` to evaluate topological drift across distributed sessions and scan for host-environment pipeline blockers (e.g., strict git hooks, missing `systemd` linger).
36
40
37
41
---
38
42
39
43
## Key Invariants
40
44
41
-
1.**Index Isolation:** The `daemon` module MUST ALWAYS set `os.environ["GIT_INDEX_FILE"]` to a temporary path before performing write operations.
42
-
2.**Zero-Destruction:** The `prune` logic in `ops.py` relies on strictly namespaced refspecs (`refs/heads/wip/pulsar/...`) and never touches standard heads.
43
-
3.**Identity Stability:** The `system` module guarantees that a Machine ID persists across reboots, preventing "Split Brain" backup histories.
44
-
4.**Configuration Precedence:** Local project configuration MUST always override global user settings to ensure repo-specific constraints (e.g., large file limits) are respected.
45
-
5.**State Over Events:** The diagnostic engine (`cli.py`) MUST prioritize current repository and environmental state over historical log events to prevent alert fatigue from self-healing anomalies.
45
+
1.**Index Isolation:** The `daemon` module MUST ALWAYS set `os.environ["GIT_INDEX_FILE"]` to a temporary path before performing write operations.
46
+
2.**Zero-Destruction:** The `prune` logic in `ops.py` relies on strictly namespaced refspecs (`refs/heads/wip/pulsar/...`) and never touches standard heads.
47
+
3.**Identity Stability:** The `system` module guarantees that a Machine ID persists across reboots, preventing "Split Brain" backup histories.
48
+
4.**Configuration Precedence:** Local project configuration MUST always override global user settings to ensure repo-specific constraints (e.g., large file limits) are respected.
49
+
5.**State Over Events:** The diagnostic engine (`cli.py`) MUST prioritize current repository and environmental state over historical log events to prevent alert fatigue from self-healing anomalies.
0 commit comments