@wipcomputer/wip-ldm-os 0.4.87-alpha.1 → 0.4.87-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -102,6 +102,11 @@ exit 0
102
102
  assert((readFileSync(shimPath).length > 0), 'foreign shim remains non-empty', output);
103
103
  assert((statSync(shimPath).mode & 0o111) !== 0, 'foreign shim remains executable', output);
104
104
  assert((existsSync(join(binDir, 'ldm-backup.sh'))), 'ldm-owned scripts still deploy into ~/.ldm/bin', output);
105
+ assert((existsSync(join(binDir, 'ldm-backup-engine.py'))), 'backup engine deploys into ~/.ldm/bin', output);
106
+ assert((existsSync(join(binDir, 'ldm-backup-policy.json'))), 'backup policy deploys into ~/.ldm/bin', output);
107
+ assert((statSync(join(binDir, 'ldm-backup-engine.py')).mode & 0o111) !== 0, 'backup engine is executable', output);
108
+ assert((statSync(join(binDir, 'ldm-backup-policy.json')).mode & 0o111) === 0, 'backup policy is not executable', output);
109
+ assert(readFileSync(join(binDir, 'ldm-backup-policy.json'), 'utf8') === readFileSync(join(repo, 'scripts', 'ldm-backup-policy.json'), 'utf8'), 'backup policy content matches package source', output);
105
110
 
106
111
  const restored = readFileSync(shimPath);
107
112
  assert(restored.length === Buffer.byteLength(shimContent), 'foreign shim size is unchanged', output);
@@ -16,7 +16,7 @@ If something is wrong, update `~/.ldm/config.json` or run `ldm install`. The doc
16
16
  | `what-is-dotldm.md` | The `~/.ldm/` runtime directory explained |
17
17
  | `directory-map.md` | What lives where and why |
18
18
  | `how-worktrees-work.md` | Git worktrees, the _worktrees/ convention |
19
- | `how-backup-works.md` | Daily backup, iCloud offsite, restore |
19
+ | `how-backup-works.md` | Safe dry run, verified internal snapshots, and later-tier gates |
20
20
  | `how-releases-work.md` | The full release pipeline |
21
21
  | `how-install-works.md` | ldm install, the install prompt, dogfooding |
22
22
  | `how-agents-work.md` | Agents, harnesses, bridge, memory |
@@ -43,7 +43,7 @@
43
43
  hooks/ <- Claude Code hooks
44
44
  state/ <- runtime state
45
45
  tmp/ <- install staging
46
- backups/ <- daily backups (ldm-backup.sh) + iCloud offsite tars
46
+ backups/v1/internal/ <- verified internal snapshots and in-progress staging
47
47
  ```
48
48
 
49
49
  ## Harness Directories (deployment targets)
@@ -1,111 +1,78 @@
1
1
  # How Backup Works
2
2
 
3
- ## One Script, One Place
3
+ ## Safe planning first
4
4
 
5
- `~/.ldm/bin/ldm-backup.sh` runs daily at 3:00 AM via LaunchAgent `ai.openclaw.ldm-backup`. It backs up everything to `~/.ldm/backups/`, then tars it to iCloud for offsite.
5
+ The backup engine has a strictly read-only dry run:
6
6
 
7
- ## What Gets Backed Up
7
+ ```bash
8
+ ~/.ldm/bin/ldm-backup.sh --dry-run
9
+ ```
8
10
 
9
- | Source | Method | What's in it |
10
- |--------|--------|-------------|
11
- | `~/.ldm/memory/crystal.db` | sqlite3 .backup | Irreplaceable memory (all agents) |
12
- | `~/.ldm/agents/` | cp -a | Identity files, journals, daily logs |
13
- | `~/.ldm/state/` | cp -a | Config, version, registry |
14
- | `~/.ldm/config.json` | cp | Workspace pointer, org |
15
- | `~/.openclaw/memory/main.sqlite` | sqlite3 .backup | OC conversations |
16
- | `~/.openclaw/memory/context-embeddings.sqlite` | sqlite3 .backup | Embeddings |
17
- | `~/.openclaw/workspace/` | tar | Shared context, daily logs |
18
- | `~/.openclaw/agents/main/sessions/` | tar | OC session JSONL |
19
- | `~/.openclaw/openclaw.json` | cp | OC config |
20
- | `~/.claude/CLAUDE.md` | cp | CC instructions |
21
- | `~/.claude/settings.json` | cp | CC settings |
22
- | `~/.claude/projects/` | tar | CC auto-memory + transcripts |
23
- | `~/wipcomputerinc/` | tar (excludes node_modules, .git/objects, old backups, _trash) | Entire workspace |
11
+ It shows every policy source, classification, exclusion reason, per-source estimate, total estimated new bytes, available disk capacity, required reserve, planned staging path, planned internal destination, blocked requirements, and the final preflight verdict.
24
12
 
25
- **NOT backed up:** node_modules/, .git/objects/ (reconstructable), extensions (reinstallable), ~/.claude/cache.
13
+ Dry run does not create files or directories. It does not acquire the persistent lock, write state, copy data, create a manifest, create a completion marker, rotate snapshots, write to Vault or iCloud, change the schedule, enable the LaunchAgent, or modify containment state. Sensitive filenames and contents are not printed.
26
14
 
27
- ## Backup Structure
15
+ Exit zero means the proposed run passes the same policy and preflight used by the real engine. Exit nonzero means a required source, encryption gate, destination, or disk reserve blocks the run.
28
16
 
29
- ```
30
- ~/.ldm/backups/2026-03-24--09-50-22/
31
- ldm/
32
- memory/crystal.db
33
- agents/
34
- state/
35
- config.json
36
- openclaw/
37
- memory/main.sqlite
38
- memory/context-embeddings.sqlite
39
- workspace.tar
40
- sessions.tar
41
- openclaw.json
42
- claude/
43
- CLAUDE.md
44
- settings.json
45
- projects.tar
46
- wipcomputerinc.tar
47
- ```
17
+ ## Canonical source policy
48
18
 
49
- ## iCloud Offsite
19
+ `~/.ldm/bin/ldm-backup-policy.json` defines required, rebuildable, sensitive, blocked, manifest-only, and excluded sources. Estimation, capture, manifest generation, and exclusion records all use this one policy.
50
20
 
51
- After local backup, the entire dated folder is compressed and copied to iCloud. The iCloud path is read from `~/.ldm/config.json` at `paths.icloudBackup`.
21
+ Sources that require encryption remain visibly blocked until that later gate ships. The engine never turns a blocked or missing required source into a partial success.
52
22
 
53
- ```
54
- ~/Library/Mobile Documents/com~apple~CloudDocs/wipcomputerinc-icloud/backups/
55
- wipcomputerinc-lesa-2026-03-24--09-50-22.tar.gz
56
- ```
23
+ The policy has one explicit ID for every approved source-inventory row. The test suite compares the exact ID list so a future omission cannot silently pass.
57
24
 
58
- One file per backup. iCloud syncs it across devices. Rotates to {{backup.keep}} days.
25
+ ## Runtime and changing files
59
26
 
60
- ## How to Run
27
+ The engine uses Python 3 standard library only. No third-party Python packages are required. If `python3` is unavailable, the runner exits with `Backup failed [python3-missing]`. Owner acceptance of Python 3 as a release prerequisite must be recorded separately at the release gate.
61
28
 
62
- ```bash
63
- ~/.ldm/bin/ldm-backup.sh # run backup now
64
- ~/.ldm/bin/ldm-backup.sh --dry-run # preview what would be backed up
65
- ~/.ldm/bin/ldm-backup.sh --keep 14 # keep 14 days instead of 7
66
- ~/.ldm/bin/ldm-backup.sh --include-secrets # include ~/.ldm/secrets/
67
- ```
29
+ A real run observes each source again immediately before capture. Changes since dry-run or initial planning are recorded and captured from the newer observation. Files and trees must then remain stable while that source is copied. Same-size changes are detected by checksum, and any during-capture mutation fails the run. SQLite uses the SQLite backup API for a transactionally consistent snapshot.
68
30
 
69
- ## How to Restore
31
+ The engine recalculates the reserve before copying a changed source. It includes staged bytes, stat-only refreshed remaining sources, a full checksum observation of the source about to be copied, projected metadata, and the required 10 percent reserve. Growth that crosses the floor fails before that source is copied.
70
32
 
71
- ```bash
72
- ~/.ldm/bin/ldm-restore.sh # list available backups
73
- ~/.ldm/bin/ldm-restore.sh 2026-03-24--09-50-22 # restore everything
74
- ~/.ldm/bin/ldm-restore.sh --only ldm <backup> # restore only crystal.db + agents
75
- ~/.ldm/bin/ldm-restore.sh --only openclaw <backup> # restore only OC data
76
- ~/.ldm/bin/ldm-restore.sh --from-icloud <file> # restore from iCloud tar
77
- ~/.ldm/bin/ldm-restore.sh --dry-run <backup> # preview
33
+ Manifest-only requirements must produce validated machine-readable evidence. An entry without an implemented generator is marked blocked before its source path is walked. When a required evidence generator is not implemented, including repo-aware Git/worktree and system inventories, the source stays blocked instead of being treated as fulfilled.
34
+
35
+ ## Successful snapshot
36
+
37
+ A completed internal snapshot lives under:
38
+
39
+ ```text
40
+ ~/.ldm/backups/v1/internal/<snapshot-id>/
78
41
  ```
79
42
 
80
- After restore: `openclaw gateway restart` then `crystal status` to verify.
43
+ It is built first as `.in-progress-<snapshot-id>`. Promotion happens only after every required capture succeeds, SQLite copies pass `PRAGMA quick_check`, checksums validate, the manifest validates, and `completion.json` is written last.
44
+
45
+ Any required failure exits nonzero, writes no completion marker, and never prints `Backup complete`.
46
+
47
+ ## Retention
48
+
49
+ The engine retains {{backup.keep}} unpinned verified snapshots plus every pinned snapshot. Pinned snapshots do not consume an unpinned retention slot. In-progress and unverified directories are never rotated.
50
+
51
+ ## Structured state
52
+
53
+ Diagnostic state lives under `~/.ldm/state/backup/v1/`:
54
+
55
+ - `schedule.json`
56
+ - `attempt.json`
57
+ - `result.json`
58
+ - `success-local.json`
81
59
 
82
- ## Schedule
60
+ State records are atomic, but they are not completion proof. A snapshot requires a valid manifest and completion marker.
83
61
 
84
- | What | When | How |
85
- |------|------|-----|
86
- | Backup | 3:00 AM | LaunchAgent `ai.openclaw.ldm-backup` runs `~/.ldm/bin/ldm-backup.sh` |
62
+ Snapshot identifiers use UTC and end in `Z`. If no valid containment marker is present, schedule state records evidence status as `unknown`.
87
63
 
88
- One LaunchAgent. One script. No Full Disk Access currently (target: midnight via LDMDevTools.app once PID error is fixed). Verify is built into the script (exit code + log).
64
+ ## Current boundaries
89
65
 
90
- ## Config
66
+ This engine correctness slice covers the internal tier. Vault, iCloud, monitoring, isolated restore, migration, and schedule resumption remain separately gated. Do not run a real backup until those gates are approved.
91
67
 
92
- All backup settings live in `~/.ldm/config.json`:
93
- - `paths.workspace` ... workspace path
94
- - `paths.icloudBackup` ... iCloud offsite destination
95
- - `backup.keep` ... retention days (default: 7)
96
- - `backup.includeSecrets` ... whether to include `~/.ldm/secrets/`
97
- - `org` ... used for tar filename prefix
68
+ ## Your system
98
69
 
99
- ## Logs
70
+ **Internal destination:** `~/.ldm/backups/v1/internal/`
100
71
 
101
- `~/.ldm/logs/backup.log` (LaunchAgent stdout/stderr)
72
+ **Configured iCloud path:** `~/Library/Mobile Documents/com~apple~CloudDocs/wipcomputerinc-icloud/backups/` (not written by this engine slice)
102
73
 
103
- ---
74
+ **Schedule label:** `ai.openclaw.ldm-backup`
104
75
 
105
- ## Your System
76
+ **Retention:** {{backup.keep}} unpinned verified snapshots
106
77
 
107
- **Local backups:** `~/.ldm/backups/`
108
- **iCloud offsite:** `~/Library/Mobile Documents/com~apple~CloudDocs/wipcomputerinc-icloud/backups/`
109
- **Schedule:** 3:00 AM via LaunchAgent `ai.openclaw.ldm-backup`
110
- **Retention:** {{backup.keep}} days local, {{backup.keep}} days iCloud
111
- **Script:** `~/.ldm/bin/ldm-backup.sh` (deployed by `ldm install`)
78
+ **Runner:** `~/.ldm/bin/ldm-backup.sh`
@@ -33,7 +33,7 @@ Where LDM OS runs. Rules, commands, and skills are authored here and deployed to
33
33
  | `~/.ldm/hooks/` | Claude Code hooks | ldm install |
34
34
  | `~/.ldm/state/` | Runtime state | Tools (watermarks, markers) |
35
35
  | `~/.ldm/tmp/` | Install staging | ldm install (cleaned after) |
36
- | `~/.ldm/backups/` | Local backups + iCloud offsite tars | ldm-backup.sh |
36
+ | `~/.ldm/backups/v1/internal/` | Verified internal snapshots and in-progress staging | ldm-backup.sh |
37
37
 
38
38
  ## Harness Directories (deployment targets)
39
39
 
@@ -41,7 +41,7 @@ The LDM OS runtime directory. Everything the system needs to run lives here. You
41
41
  hooks/ Claude Code hooks
42
42
  state/ runtime state (last release marker, watermarks)
43
43
  tmp/ install staging (cleaned after install)
44
- backups/ daily backup output (local + iCloud offsite)
44
+ backups/v1/internal/ verified internal snapshots and in-progress staging
45
45
  ```
46
46
 
47
47
  ## What Gets Backed Up
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": "lesa-bridge",
3
+ "name": "LDM Bridge",
4
+ "description": "Agent-to-agent communication and shared-memory access through LDM OS.",
5
+ "activation": {
6
+ "onStartup": true
7
+ },
8
+ "configSchema": {
9
+ "type": "object",
10
+ "additionalProperties": false,
11
+ "properties": {}
12
+ }
13
+ }
@@ -4,6 +4,9 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "WIP Bridge ... agent-to-agent communication, memory search, skill bridging. Core module of LDM OS.",
7
+ "openclaw": {
8
+ "extensions": ["./dist/openclaw.js"]
9
+ },
7
10
  "dependencies": {
8
11
  "@modelcontextprotocol/sdk": "^1.12.1",
9
12
  "better-sqlite3": "^11.8.1",