skillwiki 0.9.37 → 0.9.39
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.
- package/dist/{chunk-TK4ZIQNE.js → chunk-XBYPWCIS.js} +16 -4
- package/dist/cli.js +91 -19
- package/dist/skillwiki-mcp.js +1 -1
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +1 -1
- package/skills/.codex-plugin/plugin.json +1 -1
- package/skills/package.json +1 -1
- package/skills/skills/using-skillwiki/SKILL.md +5 -1
- package/skills/skills/wiki-sync/SKILL.md +3 -1
- package/skills/using-skillwiki/SKILL.md +5 -1
- package/skills/wiki-sync/SKILL.md +3 -1
|
@@ -1110,7 +1110,13 @@ async function runOrphans(input) {
|
|
|
1110
1110
|
if (input.vault) {
|
|
1111
1111
|
vault = input.vault;
|
|
1112
1112
|
} else {
|
|
1113
|
-
const r = await resolveRuntimePath({
|
|
1113
|
+
const r = await resolveRuntimePath({
|
|
1114
|
+
flag: void 0,
|
|
1115
|
+
envValue: input.envValue,
|
|
1116
|
+
home: input.home ?? "",
|
|
1117
|
+
wiki: input.wiki,
|
|
1118
|
+
cwd: input.cwd
|
|
1119
|
+
});
|
|
1114
1120
|
if (!r.ok) {
|
|
1115
1121
|
const exitCode = r.error === "UNKNOWN_WIKI_PROFILE" ? ExitCode.UNKNOWN_WIKI_PROFILE : ExitCode.NO_VAULT_CONFIGURED;
|
|
1116
1122
|
return { exitCode, result: r };
|
|
@@ -4399,7 +4405,7 @@ function formatKnownContext(input) {
|
|
|
4399
4405
|
const selfAliases = collectSelfAliases(input.manifest, input.hostId);
|
|
4400
4406
|
const outbound = collectOutboundAccess(input.manifest, input.hostId);
|
|
4401
4407
|
const maintenanceLines = formatMaintenanceLines(host);
|
|
4402
|
-
const guidance = host.role === "snapshotter" && host.protected === true ? `this session is already on \`${input.hostId}\`; this is a protected snapshotter host. Do not mutate
|
|
4408
|
+
const guidance = host.role === "snapshotter" && host.protected === true ? `this session is already on \`${input.hostId}\`; this is a protected snapshotter host. Live-vault authoring at the resolved \`skillwiki path\` is allowed here. Do not mutate snapshot worktrees or repo-local project workspaces from this session except explicitly approved snapshot maintenance. Keep release-validation workflows read-only when they are documented as such.` : input.hostId === "macos-dev" ? "use declared SSH aliases for remote work when needed; do not assume undeclared hosts have reciprocal SSH access." : `this session is already on \`${input.hostId}\`; do not SSH to self aliases unless the user explicitly asks. Do not assume outbound SSH to other fleet hosts is configured.`;
|
|
4403
4409
|
return [
|
|
4404
4410
|
"## Runtime Host Context",
|
|
4405
4411
|
"",
|
|
@@ -6393,7 +6399,12 @@ async function runDoctor(input) {
|
|
|
6393
6399
|
checks.push(await checkConfigFile(input.home));
|
|
6394
6400
|
checks.push(await checkProfiles(input.home));
|
|
6395
6401
|
checks.push(await checkProjectLocalOverride(input.cwd));
|
|
6396
|
-
const resolved = await resolveRuntimePath({
|
|
6402
|
+
const resolved = await resolveRuntimePath({
|
|
6403
|
+
flag: void 0,
|
|
6404
|
+
envValue: input.envValue,
|
|
6405
|
+
home: input.home,
|
|
6406
|
+
cwd: input.cwd
|
|
6407
|
+
});
|
|
6397
6408
|
if (resolved.ok) {
|
|
6398
6409
|
checks.push(check("pass", "wiki_path_set", "WIKI_PATH configured", `Resolved via ${resolved.data.source}: ${resolved.data.path}`));
|
|
6399
6410
|
} else {
|
|
@@ -7923,7 +7934,8 @@ async function resolveMcpVault(input) {
|
|
|
7923
7934
|
envValue: process.env.WIKI_PATH,
|
|
7924
7935
|
wikiEnv: process.env.WIKI,
|
|
7925
7936
|
home,
|
|
7926
|
-
wiki: input.wiki
|
|
7937
|
+
wiki: input.wiki,
|
|
7938
|
+
cwd: input.cwd ?? process.cwd()
|
|
7927
7939
|
});
|
|
7928
7940
|
if (!r.ok) return r;
|
|
7929
7941
|
vaultPath = resolve7(r.data.path);
|
package/dist/cli.js
CHANGED
|
@@ -75,13 +75,13 @@ import {
|
|
|
75
75
|
triggerAutoUpdate,
|
|
76
76
|
writeCache,
|
|
77
77
|
writeDotenv
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-XBYPWCIS.js";
|
|
79
79
|
import {
|
|
80
80
|
normalizeDistTag
|
|
81
81
|
} from "./chunk-E6UWZ3S3.js";
|
|
82
82
|
|
|
83
83
|
// src/cli.ts
|
|
84
|
-
import { join as
|
|
84
|
+
import { join as join26 } from "path";
|
|
85
85
|
import { Command } from "commander";
|
|
86
86
|
|
|
87
87
|
// src/utils/output.ts
|
|
@@ -425,6 +425,7 @@ async function runPath(input) {
|
|
|
425
425
|
flag: input.flag,
|
|
426
426
|
envValue: input.envValue,
|
|
427
427
|
home: input.home,
|
|
428
|
+
cwd: input.cwd,
|
|
428
429
|
explain: input.explain
|
|
429
430
|
});
|
|
430
431
|
return { exitCode: ExitCode.OK, result: ok({ path: r2.path, source: r2.source, ...r2.chain ? { chain: r2.chain } : {}, humanHint: `${r2.path} (via ${r2.source})` }) };
|
|
@@ -434,6 +435,7 @@ async function runPath(input) {
|
|
|
434
435
|
envValue: input.envValue,
|
|
435
436
|
home: input.home,
|
|
436
437
|
wiki: input.wiki,
|
|
438
|
+
cwd: input.cwd,
|
|
437
439
|
explain: input.explain
|
|
438
440
|
});
|
|
439
441
|
if (!r.ok) {
|
|
@@ -4795,13 +4797,19 @@ async function postCommit(vault, exitCode) {
|
|
|
4795
4797
|
}
|
|
4796
4798
|
|
|
4797
4799
|
// src/utils/protected-vault-write-guard.ts
|
|
4800
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
4801
|
+
import { join as join25, resolve as resolvePath } from "path";
|
|
4798
4802
|
async function guardProtectedVaultWrite(input) {
|
|
4803
|
+
const env = input.env ?? process.env;
|
|
4804
|
+
const home = input.home ?? process.env.HOME ?? "";
|
|
4805
|
+
const cwd = input.cwd ?? process.cwd();
|
|
4806
|
+
const liveVaultPath = await resolveLiveVaultPath({ env, home, cwd });
|
|
4799
4807
|
const load = await loadFleetManifestAndHost({
|
|
4800
|
-
vault: input.vault,
|
|
4808
|
+
vault: liveVaultPath ?? input.vault,
|
|
4801
4809
|
hostId: input.hostId,
|
|
4802
|
-
env
|
|
4803
|
-
home
|
|
4804
|
-
cwd
|
|
4810
|
+
env,
|
|
4811
|
+
home,
|
|
4812
|
+
cwd,
|
|
4805
4813
|
osHostname: input.osHostname ?? process.env.HOSTNAME,
|
|
4806
4814
|
user: input.user ?? process.env.USER
|
|
4807
4815
|
});
|
|
@@ -4812,16 +4820,77 @@ async function guardProtectedVaultWrite(input) {
|
|
|
4812
4820
|
if (!host || host.role !== "snapshotter" || host.protected !== true) {
|
|
4813
4821
|
return { blocked: false };
|
|
4814
4822
|
}
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4823
|
+
const snapshotWorktree = resolveSnapshotWorktree(home);
|
|
4824
|
+
const targetVault = resolvePath(input.vault);
|
|
4825
|
+
const canonicalLiveVault = liveVaultPath ? resolvePath(liveVaultPath) : void 0;
|
|
4826
|
+
const canonicalSnapshotWorktree = snapshotWorktree ? resolvePath(snapshotWorktree) : void 0;
|
|
4827
|
+
if (canonicalLiveVault && targetVault === canonicalLiveVault) {
|
|
4828
|
+
return { blocked: false };
|
|
4829
|
+
}
|
|
4830
|
+
if (canonicalSnapshotWorktree && targetVault === canonicalSnapshotWorktree) {
|
|
4831
|
+
return {
|
|
4832
|
+
blocked: true,
|
|
4833
|
+
exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED,
|
|
4834
|
+
result: err("PROTECTED_SNAPSHOTTER_WRITE_BLOCKED", {
|
|
4835
|
+
host_id: load.hostId,
|
|
4836
|
+
command: input.command,
|
|
4837
|
+
reason: `refusing mutation of snapshot worktree '${canonicalSnapshotWorktree}' on protected snapshotter host '${load.hostId}'`,
|
|
4838
|
+
guidance: canonicalLiveVault ? `Use the live vault path '${canonicalLiveVault}' for authoring. Keep snapshot worktrees read-only except explicit snapshot maintenance.` : "Use the live skillwiki vault path for authoring. Keep snapshot worktrees read-only except explicit snapshot maintenance."
|
|
4839
|
+
})
|
|
4840
|
+
};
|
|
4841
|
+
}
|
|
4842
|
+
if (canonicalLiveVault && targetVault !== canonicalLiveVault) {
|
|
4843
|
+
return {
|
|
4844
|
+
blocked: true,
|
|
4845
|
+
exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED,
|
|
4846
|
+
result: err("PROTECTED_SNAPSHOTTER_WRITE_BLOCKED", {
|
|
4847
|
+
host_id: load.hostId,
|
|
4848
|
+
command: input.command,
|
|
4849
|
+
reason: `refusing vault mutation outside the live vault path '${canonicalLiveVault}' on protected snapshotter host '${load.hostId}'`,
|
|
4850
|
+
guidance: "Use the resolved live skillwiki vault path for authoring. Keep alternate vault roots and snapshot worktrees read-only unless explicitly approved."
|
|
4851
|
+
})
|
|
4852
|
+
};
|
|
4853
|
+
}
|
|
4854
|
+
return { blocked: false };
|
|
4855
|
+
}
|
|
4856
|
+
async function resolveLiveVaultPath(input) {
|
|
4857
|
+
const resolved = await resolveRuntimePath({
|
|
4858
|
+
flag: void 0,
|
|
4859
|
+
envValue: input.env.WIKI_PATH,
|
|
4860
|
+
wikiEnv: input.env.WIKI,
|
|
4861
|
+
home: input.home,
|
|
4862
|
+
cwd: input.cwd
|
|
4863
|
+
});
|
|
4864
|
+
return resolved.ok ? resolved.data.path : void 0;
|
|
4865
|
+
}
|
|
4866
|
+
function resolveSnapshotWorktree(home) {
|
|
4867
|
+
const skillwikiEnv = join25(home, ".skillwiki", ".env");
|
|
4868
|
+
const explicitWorktree = readEnvKey(skillwikiEnv, ["vault_sync.snapshot_worktree"]);
|
|
4869
|
+
if (explicitWorktree) return explicitWorktree;
|
|
4870
|
+
const snapshotProfile = readEnvKey(skillwikiEnv, ["vault_sync.snapshot_profile"]);
|
|
4871
|
+
if (snapshotProfile) {
|
|
4872
|
+
const fromProfile = readEnvKey(snapshotProfile, ["WIKI_GIT_WORKTREE", "SNAPSHOT_WORKTREE", "GIT_DIR"]);
|
|
4873
|
+
if (fromProfile) return fromProfile;
|
|
4874
|
+
}
|
|
4875
|
+
return "/root/wiki-git";
|
|
4876
|
+
}
|
|
4877
|
+
function readEnvKey(path, keys) {
|
|
4878
|
+
try {
|
|
4879
|
+
const content = readFileSync7(path, "utf8");
|
|
4880
|
+
for (const line of content.split(/\r?\n/)) {
|
|
4881
|
+
const trimmed = line.trim();
|
|
4882
|
+
if (trimmed.length === 0 || trimmed.startsWith("#")) continue;
|
|
4883
|
+
const eq = trimmed.indexOf("=");
|
|
4884
|
+
if (eq <= 0) continue;
|
|
4885
|
+
const key = trimmed.slice(0, eq).trim();
|
|
4886
|
+
if (!keys.includes(key)) continue;
|
|
4887
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
4888
|
+
if (value.length > 0) return value;
|
|
4889
|
+
}
|
|
4890
|
+
} catch {
|
|
4891
|
+
return void 0;
|
|
4892
|
+
}
|
|
4893
|
+
return void 0;
|
|
4825
4894
|
}
|
|
4826
4895
|
|
|
4827
4896
|
// src/cli.ts
|
|
@@ -4865,7 +4934,7 @@ program.command("validate <file>").description("validate vault page frontmatter
|
|
|
4865
4934
|
emit(await runValidate({ file, apply: !!opts.apply, vault }), vault);
|
|
4866
4935
|
});
|
|
4867
4936
|
program.command("graph").description("graph subcommands").command("build <vault>").option("--out <path>", "graph output path (default: <vault>/.skillwiki/graph.json)").option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
|
|
4868
|
-
const out = opts.out ??
|
|
4937
|
+
const out = opts.out ?? join26(vault, ".skillwiki", "graph.json");
|
|
4869
4938
|
return emitGuardedVaultWrite(vault, "graph build", () => runGraphBuild({ vault, out }));
|
|
4870
4939
|
});
|
|
4871
4940
|
var canvasCmd = program.command("canvas").description("manage Obsidian canvas files");
|
|
@@ -4888,7 +4957,8 @@ program.command("orphans [vault]").description("find pages not referenced by any
|
|
|
4888
4957
|
vault,
|
|
4889
4958
|
envValue: process.env.WIKI_PATH,
|
|
4890
4959
|
home: process.env.HOME ?? "",
|
|
4891
|
-
wiki: opts.wiki
|
|
4960
|
+
wiki: opts.wiki,
|
|
4961
|
+
cwd: process.cwd()
|
|
4892
4962
|
})));
|
|
4893
4963
|
program.command("audit <file>").description("audit citation markers and source provenance for a vault page").action(async (file) => emit(await runAudit({ file })));
|
|
4894
4964
|
program.command("install").description("install skillwiki SKILL.md files into ~/.claude/skills/").option("--target <dir>", "target install directory", `${process.env.HOME ?? ""}/.claude/skills/`).option("--dry-run", "preview only", false).option("--skills-root <dir>", "source skills directory (defaults to packaged)").option("--symlink", "create symlinks instead of copies (dev mode \u2014 edits to source are immediately visible)", false).option("--force", "install CLI copies even when the skillwiki@llm-wiki plugin channel is active", false).action(async (opts) => {
|
|
@@ -4904,6 +4974,7 @@ program.command("path").description("show the resolved vault path").option("--va
|
|
|
4904
4974
|
home: process.env.HOME ?? "",
|
|
4905
4975
|
initTime,
|
|
4906
4976
|
wiki: opts.wiki,
|
|
4977
|
+
cwd: process.cwd(),
|
|
4907
4978
|
explain: !!opts.explain
|
|
4908
4979
|
}));
|
|
4909
4980
|
});
|
|
@@ -4938,7 +5009,8 @@ async function resolveVaultArg(arg, wiki) {
|
|
|
4938
5009
|
envValue: process.env.WIKI_PATH,
|
|
4939
5010
|
wikiEnv: process.env.WIKI,
|
|
4940
5011
|
home: process.env.HOME ?? "",
|
|
4941
|
-
wiki
|
|
5012
|
+
wiki,
|
|
5013
|
+
cwd: process.cwd()
|
|
4942
5014
|
});
|
|
4943
5015
|
if (!r.ok) {
|
|
4944
5016
|
const exitCode = r.error === "UNKNOWN_WIKI_PROFILE" ? 35 : 25;
|
package/dist/skillwiki-mcp.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.39",
|
|
4
4
|
"skills": "./",
|
|
5
5
|
"description": "Project-aware Karpathy-style knowledge base for Claude Code: 18 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI.",
|
|
6
6
|
"author": {
|
package/skills/package.json
CHANGED
|
@@ -124,7 +124,11 @@ Key CLI subcommands: `init`, `health`, `lint`, `config`, `doctor`, `path`, `lang
|
|
|
124
124
|
Run `skillwiki health <vault> --out /tmp/skillwiki-health.json --no-fail` for a bounded whole-system report that includes doctor, lint, vault-sync, query-readiness, source-freshness, risk flags, and self-check coverage. Run `skillwiki lint <vault> --summary` for lint-only bucket counts with capped examples and details commands. Run `skillwiki doctor` to diagnose setup/runtime issues only. Run `skillwiki config list` to see current configuration.
|
|
125
125
|
|
|
126
126
|
## Runtime Host Context and Fleet Freshness
|
|
127
|
-
|
|
127
|
+
Resolve the active project vault with `skillwiki path` first. Then pass that exact path to `skillwiki --human fleet context <vault>` for host identity and safety guidance. `fleet context` is authoritative for host identity. It overrides stale injected SessionStart context, remembered workspace context, and prior conversation summaries. `fleet context` is local and network-free; it reports `identity_status`, resolver trace, warnings, and the fact that remote freshness was not checked.
|
|
128
|
+
|
|
129
|
+
Do not substitute infrastructure mirrors such as `~/wiki-git` or other snapshot worktrees for the project vault just to inspect fleet status. Those paths are snapshot infrastructure unless `skillwiki path` itself resolves there.
|
|
130
|
+
|
|
131
|
+
On snapshotter hosts, `protected: true` does not by itself mean the live vault is read-only for agent authoring. Treat the resolved `skillwiki path` as the live authoring vault when the host policy allows it, and treat snapshot worktrees such as `~/wiki-git` as protected infrastructure unless the user explicitly asks for snapshot maintenance.
|
|
128
132
|
|
|
129
133
|
Use the local identity check for ordinary runtime context:
|
|
130
134
|
```bash
|
|
@@ -182,6 +182,8 @@ Some deployments use a cloud-backed vault (`rclone mount`) with a separate git r
|
|
|
182
182
|
~/wiki-git → git repository cloned from GitHub — snapshot target
|
|
183
183
|
cron hourly → rsync ~/wiki/ → ~/wiki-git/ → git commit → git push
|
|
184
184
|
```
|
|
185
|
+
On snapshotter hosts, `~/wiki` remains the active SkillWiki vault for path resolution unless the operator explicitly configures otherwise. `~/wiki-git` is snapshot infrastructure, not the default authoring or dev-loop vault. Agents may author the live vault path when the host policy allows it, but should not point project work or `fleet context` at `~/wiki-git` unless `skillwiki path` intentionally resolves there.
|
|
186
|
+
|
|
185
187
|
### Implementation (wiki-snapshot.sh)
|
|
186
188
|
```bash
|
|
187
189
|
#!/bin/bash
|
|
@@ -217,7 +219,7 @@ git reset --hard origin/main
|
|
|
217
219
|
bash ~/.hermes/scripts/wiki-snapshot.sh # Re-sync fresh
|
|
218
220
|
```
|
|
219
221
|
**Prevention**: Avoid editing the GitHub repo directly via web interface or uncoordinated clones. The canonical flow is **single-writer-git** (see `concepts/vault-write-authority-model.md`):
|
|
220
|
-
- Server (sg01):
|
|
222
|
+
- Server (sg01): agents may author the live vault at `~/wiki`; the snapshot job promotes cloud-backed live-vault state into `~/wiki-git`, then commits and pushes — **sole git writer to `main`**
|
|
221
223
|
- macOS/desktop: edit → `wiki-push` rclone copy to S3 (NO git push) → consume sg01 snapshots via `wiki-fetch-notify` (opt-in `WIKI_FETCH_PULL_ON_DELTA=1`) or manual `skillwiki sync`
|
|
222
224
|
- `wiki-sync` skill push is for **explicit** agent/human edit commits only, not automated background pushes
|
|
223
225
|
2. **Slow rsync on rclone mounts**: The rclone FUSE mount can be slow for large directory listings. Use `rsync -q` (quiet) to reduce output overhead, and consider `--delete-delay` instead of `--delete` if file churn is high. The rclone mount latency can cause `du` and `find` operations to timeout — this is normal, not an error.
|
|
@@ -124,7 +124,11 @@ Key CLI subcommands: `init`, `health`, `lint`, `config`, `doctor`, `path`, `lang
|
|
|
124
124
|
Run `skillwiki health <vault> --out /tmp/skillwiki-health.json --no-fail` for a bounded whole-system report that includes doctor, lint, vault-sync, query-readiness, source-freshness, risk flags, and self-check coverage. Run `skillwiki lint <vault> --summary` for lint-only bucket counts with capped examples and details commands. Run `skillwiki doctor` to diagnose setup/runtime issues only. Run `skillwiki config list` to see current configuration.
|
|
125
125
|
|
|
126
126
|
## Runtime Host Context and Fleet Freshness
|
|
127
|
-
|
|
127
|
+
Resolve the active project vault with `skillwiki path` first. Then pass that exact path to `skillwiki --human fleet context <vault>` for host identity and safety guidance. `fleet context` is authoritative for host identity. It overrides stale injected SessionStart context, remembered workspace context, and prior conversation summaries. `fleet context` is local and network-free; it reports `identity_status`, resolver trace, warnings, and the fact that remote freshness was not checked.
|
|
128
|
+
|
|
129
|
+
Do not substitute infrastructure mirrors such as `~/wiki-git` or other snapshot worktrees for the project vault just to inspect fleet status. Those paths are snapshot infrastructure unless `skillwiki path` itself resolves there.
|
|
130
|
+
|
|
131
|
+
On snapshotter hosts, `protected: true` does not by itself mean the live vault is read-only for agent authoring. Treat the resolved `skillwiki path` as the live authoring vault when the host policy allows it, and treat snapshot worktrees such as `~/wiki-git` as protected infrastructure unless the user explicitly asks for snapshot maintenance.
|
|
128
132
|
|
|
129
133
|
Use the local identity check for ordinary runtime context:
|
|
130
134
|
```bash
|
|
@@ -182,6 +182,8 @@ Some deployments use a cloud-backed vault (`rclone mount`) with a separate git r
|
|
|
182
182
|
~/wiki-git → git repository cloned from GitHub — snapshot target
|
|
183
183
|
cron hourly → rsync ~/wiki/ → ~/wiki-git/ → git commit → git push
|
|
184
184
|
```
|
|
185
|
+
On snapshotter hosts, `~/wiki` remains the active SkillWiki vault for path resolution unless the operator explicitly configures otherwise. `~/wiki-git` is snapshot infrastructure, not the default authoring or dev-loop vault. Agents may author the live vault path when the host policy allows it, but should not point project work or `fleet context` at `~/wiki-git` unless `skillwiki path` intentionally resolves there.
|
|
186
|
+
|
|
185
187
|
### Implementation (wiki-snapshot.sh)
|
|
186
188
|
```bash
|
|
187
189
|
#!/bin/bash
|
|
@@ -217,7 +219,7 @@ git reset --hard origin/main
|
|
|
217
219
|
bash ~/.hermes/scripts/wiki-snapshot.sh # Re-sync fresh
|
|
218
220
|
```
|
|
219
221
|
**Prevention**: Avoid editing the GitHub repo directly via web interface or uncoordinated clones. The canonical flow is **single-writer-git** (see `concepts/vault-write-authority-model.md`):
|
|
220
|
-
- Server (sg01):
|
|
222
|
+
- Server (sg01): agents may author the live vault at `~/wiki`; the snapshot job promotes cloud-backed live-vault state into `~/wiki-git`, then commits and pushes — **sole git writer to `main`**
|
|
221
223
|
- macOS/desktop: edit → `wiki-push` rclone copy to S3 (NO git push) → consume sg01 snapshots via `wiki-fetch-notify` (opt-in `WIKI_FETCH_PULL_ON_DELTA=1`) or manual `skillwiki sync`
|
|
222
224
|
- `wiki-sync` skill push is for **explicit** agent/human edit commits only, not automated background pushes
|
|
223
225
|
2. **Slow rsync on rclone mounts**: The rclone FUSE mount can be slow for large directory listings. Use `rsync -q` (quiet) to reduce output overhead, and consider `--delete-delay` instead of `--delete` if file churn is high. The rclone mount latency can cause `du` and `find` operations to timeout — this is normal, not an error.
|