Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions packages/agent-memory-sync/docs/machine-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ This document wires together the pieces already documented individually
must be running on every fallback machine.

Machine-specific values (paths, SSH alias) are committed as profile files
under `profiles/`: `profiles/macbook.json`, `profiles/mac-mini.json`, and a
under `profiles/`: `profiles/macbook.json`, `profiles/mac-mini.json`,
`profiles/linux.json` (the Linux desktop set up via (c) below), and a
template for further machines, `profiles/linux.example.json`. Each profile
file documents its own placeholders and the namespace-divergence gotcha
in its `"//"` field — read the profile you're activating before copying
Expand Down Expand Up @@ -331,7 +332,8 @@ bullet at the top of this document.

## e) machine-state payload (toolchain snapshots)

Every committed profile (`profiles/mac-mini.json`, `profiles/macbook.json`)
Every committed machine profile (`profiles/mac-mini.json`,
`profiles/macbook.json`, `profiles/linux.json`)
carries a **second, independent** `syncPaths` entry alongside the `memory`
one described at the top of this document:

Expand Down Expand Up @@ -399,11 +401,11 @@ exist ahead of any sync.
## f) frictions payload (friction-log exports)

Every committed profile (`profiles/mac-mini.json`, `profiles/macbook.json`,
`profiles/linux.example.json`) also carries an **independent** `syncPaths`
entry pointing at `~/.harness/frictions` — the third entry in
`mac-mini.json`/`macbook.json` (after `memory` and `machine-state`), and
the second in `linux.example.json` (that template does not yet include a
`machine-state` entry):
`profiles/linux.json`, `profiles/linux.example.json`) also carries an
**independent** `syncPaths` entry pointing at `~/.harness/frictions` — the
third entry in `mac-mini.json`/`macbook.json`/`linux.json` (after `memory`
and `machine-state`), and the second in `linux.example.json` (that template
does not yet include a `machine-state` entry):

```json
{ "source": "/Users/<user>/.harness/frictions", "destination": "frictions", "kind": "directory" }
Expand Down
51 changes: 51 additions & 0 deletions packages/agent-memory-sync/profiles/linux.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"//": [
"Machine profile: Linux desktop (WSL2, DESKTOP-9TDLGAR) — fallback",
"machine. The Mac mini is the single source of truth (see mac-mini.json);",
"this machine pulls via the periodic sync timer and pushes debounced",
"snapshots via `watch`. Filled in from linux.example.json — read that",
"template's '//' field for the full rationale; the load-bearing invariants",
"restated inline: the memory entry's destination must be the literal",
"'memory', never '.' (a '.' destination is silently unmappable on",
"pull/restore); stateDir must stay OUTSIDE rootDir (the '.' walk would",
"otherwise sync the tool's own state); rootDir/stateDir are absolute,",
"the loader performs no tilde expansion. reachabilityTimeoutMs is 10000",
"like macbook.json (ssh-reached spoke), not the template's 5000.",
"",
"repositorySubdir MUST stay the fixed literal 'pandora', identical on",
"every machine sharing the remote — a per-machine value silently",
"partitions the bare repo into disjoint trees (happened before, caught by",
"a live cross-machine E2E test). See the template / machine-setup.md.",
"",
"rootDir is this machine's own Claude Code slug, read off",
"`ls ~/.claude/projects/` HERE (encodes OS user 'lan' + checkout path",
"/home/lan/git/pandora) — never copied from another machine's profile.",
"",
"Deviation from linux.example.json, deliberate: a third syncPaths entry",
"for machine-state (absolute source ~/.harness/machine-state), which the",
"template does not yet carry (noted in machine-setup.md section f) —",
"without it this machine is invisible to the toolchain-parity check.",
"Producer: `harness session-start toolchain-parity`; convention is",
"owner-writes-only, one file per machine (machine-state/linux.json).",
"",
"frictions producer: friction-log sync_export in",
"~/.config/friction-log/config.yml writes ~/.harness/frictions/linux.json.",
"",
"Activation: pass BOTH --config (this file) and the profile name",
"positionally:",
" agent-memory-sync run linux --config profiles/linux.json"
],
"profile": "linux",
"rootDir": "/home/lan/.claude/projects/-home-lan-git-pandora/memory",
"remoteUrl": "mini:~/memory-sync/pandora-memory.git",
"branch": "main",
"repositorySubdir": "pandora",
"stateDir": "/home/lan/.agent-memory-sync/linux",
"conflictStrategy": "inline-markers",
"reachabilityTimeoutMs": 10000,
"syncPaths": [
{ "source": ".", "destination": "memory", "kind": "directory" },
{ "source": "/home/lan/.harness/machine-state", "destination": "machine-state", "kind": "directory" },
{ "source": "/home/lan/.harness/frictions", "destination": "frictions", "kind": "directory" }
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,16 @@ test("macbook and mac-mini profiles share one remote tree and see each other's p
);
});

test("profiles/macbook.json, profiles/mac-mini.json, and profiles/linux.example.json all declare the same repositorySubdir", () => {
test("all committed profiles (macbook, mac-mini, linux, linux.example) declare the same repositorySubdir", () => {
// A narrower, faster companion to the end-to-end test above: pins the
// specific config field that caused the divergence directly against the
// committed files, independent of any CLI/git plumbing. Includes
// linux.example.json — the copy-paste source for any new machine — so a
// future template edit that reintroduces a per-machine placeholder (as
// this template originally had, mirroring the pre-fix macbook/mac-mini
// profiles) is caught here too, not just on the two profiles already in
// profiles) is caught here too, not just on the profiles already in
// active use.
const profileFiles = ["macbook.json", "mac-mini.json", "linux.example.json"];
const profileFiles = ["macbook.json", "mac-mini.json", "linux.json", "linux.example.json"];
const settingsByFile = Object.fromEntries(
profileFiles.map((file) => [file, JSON.parse(readText(path.join(PROFILES_DIR, file)))])
);
Expand Down Expand Up @@ -196,9 +196,10 @@ test("profiles/macbook.json, profiles/mac-mini.json, and profiles/linux.example.
}

// Same pin for the pre-existing machine-state entry, closing the identical
// #64 coverage gap — macbook.json and mac-mini.json only, since
// linux.example.json's template has never carried a machine-state entry.
for (const file of ["macbook.json", "mac-mini.json"]) {
// #64 coverage gap — every committed machine profile, but not
// linux.example.json, since the template has never carried a machine-state
// entry (linux.json adds it deliberately; see machine-setup.md section f).
for (const file of ["macbook.json", "mac-mini.json", "linux.json"]) {
const machineStateEntries = findEntriesByDestination(settingsByFile[file].syncPaths, "machine-state");
assert.equal(
machineStateEntries.length,
Expand Down
Loading