skillwiki 0.9.38 → 0.9.40
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-G52HKU7I.js → chunk-XBYPWCIS.js} +1 -1
- package/dist/cli.js +84 -17
- 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 +2 -0
- package/skills/skills/wiki-sync/SKILL.md +2 -2
- package/skills/using-skillwiki/SKILL.md +2 -0
- package/skills/wiki-sync/SKILL.md +2 -2
|
@@ -4405,7 +4405,7 @@ function formatKnownContext(input) {
|
|
|
4405
4405
|
const selfAliases = collectSelfAliases(input.manifest, input.hostId);
|
|
4406
4406
|
const outbound = collectOutboundAccess(input.manifest, input.hostId);
|
|
4407
4407
|
const maintenanceLines = formatMaintenanceLines(host);
|
|
4408
|
-
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.`;
|
|
4409
4409
|
return [
|
|
4410
4410
|
"## Runtime Host Context",
|
|
4411
4411
|
"",
|
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
|
|
@@ -4797,13 +4797,19 @@ async function postCommit(vault, exitCode) {
|
|
|
4797
4797
|
}
|
|
4798
4798
|
|
|
4799
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";
|
|
4800
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 });
|
|
4801
4807
|
const load = await loadFleetManifestAndHost({
|
|
4802
|
-
vault: input.vault,
|
|
4808
|
+
vault: liveVaultPath ?? input.vault,
|
|
4803
4809
|
hostId: input.hostId,
|
|
4804
|
-
env
|
|
4805
|
-
home
|
|
4806
|
-
cwd
|
|
4810
|
+
env,
|
|
4811
|
+
home,
|
|
4812
|
+
cwd,
|
|
4807
4813
|
osHostname: input.osHostname ?? process.env.HOSTNAME,
|
|
4808
4814
|
user: input.user ?? process.env.USER
|
|
4809
4815
|
});
|
|
@@ -4814,16 +4820,77 @@ async function guardProtectedVaultWrite(input) {
|
|
|
4814
4820
|
if (!host || host.role !== "snapshotter" || host.protected !== true) {
|
|
4815
4821
|
return { blocked: false };
|
|
4816
4822
|
}
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
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;
|
|
4827
4894
|
}
|
|
4828
4895
|
|
|
4829
4896
|
// src/cli.ts
|
|
@@ -4867,7 +4934,7 @@ program.command("validate <file>").description("validate vault page frontmatter
|
|
|
4867
4934
|
emit(await runValidate({ file, apply: !!opts.apply, vault }), vault);
|
|
4868
4935
|
});
|
|
4869
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) => {
|
|
4870
|
-
const out = opts.out ??
|
|
4937
|
+
const out = opts.out ?? join26(vault, ".skillwiki", "graph.json");
|
|
4871
4938
|
return emitGuardedVaultWrite(vault, "graph build", () => runGraphBuild({ vault, out }));
|
|
4872
4939
|
});
|
|
4873
4940
|
var canvasCmd = program.command("canvas").description("manage Obsidian canvas files");
|
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.40",
|
|
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
|
@@ -128,6 +128,8 @@ Resolve the active project vault with `skillwiki path` first. Then pass that exa
|
|
|
128
128
|
|
|
129
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
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.
|
|
132
|
+
|
|
131
133
|
Use the local identity check for ordinary runtime context:
|
|
132
134
|
```bash
|
|
133
135
|
VAULT="$(skillwiki --human path | sed 's/ (via.*//')"
|
|
@@ -182,7 +182,7 @@ 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.
|
|
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
186
|
|
|
187
187
|
### Implementation (wiki-snapshot.sh)
|
|
188
188
|
```bash
|
|
@@ -219,7 +219,7 @@ git reset --hard origin/main
|
|
|
219
219
|
bash ~/.hermes/scripts/wiki-snapshot.sh # Re-sync fresh
|
|
220
220
|
```
|
|
221
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`):
|
|
222
|
-
- 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`**
|
|
223
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`
|
|
224
224
|
- `wiki-sync` skill push is for **explicit** agent/human edit commits only, not automated background pushes
|
|
225
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.
|
|
@@ -128,6 +128,8 @@ Resolve the active project vault with `skillwiki path` first. Then pass that exa
|
|
|
128
128
|
|
|
129
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
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.
|
|
132
|
+
|
|
131
133
|
Use the local identity check for ordinary runtime context:
|
|
132
134
|
```bash
|
|
133
135
|
VAULT="$(skillwiki --human path | sed 's/ (via.*//')"
|
|
@@ -182,7 +182,7 @@ 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.
|
|
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
186
|
|
|
187
187
|
### Implementation (wiki-snapshot.sh)
|
|
188
188
|
```bash
|
|
@@ -219,7 +219,7 @@ git reset --hard origin/main
|
|
|
219
219
|
bash ~/.hermes/scripts/wiki-snapshot.sh # Re-sync fresh
|
|
220
220
|
```
|
|
221
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`):
|
|
222
|
-
- 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`**
|
|
223
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`
|
|
224
224
|
- `wiki-sync` skill push is for **explicit** agent/human edit commits only, not automated background pushes
|
|
225
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.
|