skillwiki 0.9.35 → 0.9.37
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/cli.js
CHANGED
|
@@ -3303,6 +3303,7 @@ ${body}`;
|
|
|
3303
3303
|
// src/commands/sync.ts
|
|
3304
3304
|
import { existsSync as existsSync7 } from "fs";
|
|
3305
3305
|
import { join as join18 } from "path";
|
|
3306
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
3306
3307
|
|
|
3307
3308
|
// src/utils/git.ts
|
|
3308
3309
|
import { execFileSync } from "child_process";
|
|
@@ -3453,6 +3454,33 @@ function stageVaultContentChanges(vault) {
|
|
|
3453
3454
|
}
|
|
3454
3455
|
|
|
3455
3456
|
// src/commands/sync.ts
|
|
3457
|
+
function parseDirtyPaths(porcelain) {
|
|
3458
|
+
if (!porcelain) return [];
|
|
3459
|
+
return porcelain.split("\n").map((line) => line.trimEnd()).filter((line) => line.length >= 4).map((line) => {
|
|
3460
|
+
const payload = line.length >= 3 && line[2] === " " ? line.slice(3) : line.length >= 2 && line[1] === " " ? line.slice(2) : line;
|
|
3461
|
+
const arrow = payload.lastIndexOf(" -> ");
|
|
3462
|
+
return arrow >= 0 ? payload.slice(arrow + 4) : payload;
|
|
3463
|
+
}).filter((path) => path.length > 0);
|
|
3464
|
+
}
|
|
3465
|
+
function splitNonEmptyLines(text) {
|
|
3466
|
+
if (!text) return [];
|
|
3467
|
+
return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
3468
|
+
}
|
|
3469
|
+
function isTrackedNotePath(path) {
|
|
3470
|
+
if (!path.endsWith(".md")) return false;
|
|
3471
|
+
return !/^\.(skillwiki|claude|obsidian|antigravitycli|playwright-cli)\//.test(path);
|
|
3472
|
+
}
|
|
3473
|
+
function refHasPath(vault, ref, path) {
|
|
3474
|
+
try {
|
|
3475
|
+
execFileSync2("git", ["cat-file", "-e", `${ref}:${path}`], {
|
|
3476
|
+
cwd: vault,
|
|
3477
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
3478
|
+
});
|
|
3479
|
+
return true;
|
|
3480
|
+
} catch {
|
|
3481
|
+
return false;
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3456
3484
|
function runSyncStatus(input) {
|
|
3457
3485
|
const vault = input.vault;
|
|
3458
3486
|
const includeStashes = input.includeStashes ?? false;
|
|
@@ -3464,6 +3492,8 @@ function runSyncStatus(input) {
|
|
|
3464
3492
|
dirty: 0,
|
|
3465
3493
|
ahead: 0,
|
|
3466
3494
|
behind: 0,
|
|
3495
|
+
unpromoted_note_paths: 0,
|
|
3496
|
+
unpromoted_note_examples: [],
|
|
3467
3497
|
last_commit: "never",
|
|
3468
3498
|
status: "not_a_repo",
|
|
3469
3499
|
humanHint: "not a git repository"
|
|
@@ -3473,6 +3503,8 @@ function runSyncStatus(input) {
|
|
|
3473
3503
|
enableGitLongPathsOnWindows(vault);
|
|
3474
3504
|
const porcelain = git(vault, ["status", "--porcelain"]);
|
|
3475
3505
|
const dirty = porcelain ? porcelain.split("\n").filter((l) => l.trim().length > 0).length : 0;
|
|
3506
|
+
const dirtyPaths = parseDirtyPaths(porcelain);
|
|
3507
|
+
const untrackedPaths = splitNonEmptyLines(git(vault, ["ls-files", "--others", "--exclude-standard"]));
|
|
3476
3508
|
const revOutput = git(vault, ["rev-list", "--left-right", "--count", "origin/HEAD...HEAD"]);
|
|
3477
3509
|
let ahead = 0;
|
|
3478
3510
|
let behind = 0;
|
|
@@ -3493,6 +3525,10 @@ function runSyncStatus(input) {
|
|
|
3493
3525
|
} else {
|
|
3494
3526
|
last_commit = "never";
|
|
3495
3527
|
}
|
|
3528
|
+
const remoteRef = git(vault, ["rev-parse", "--verify", "origin/main"]) ? "origin/main" : git(vault, ["rev-parse", "--verify", "origin/HEAD"]) ? "origin/HEAD" : "HEAD";
|
|
3529
|
+
const unpromotedNoteAll = Array.from(/* @__PURE__ */ new Set([...dirtyPaths, ...untrackedPaths])).filter(isTrackedNotePath).filter((path) => !refHasPath(vault, remoteRef, path));
|
|
3530
|
+
const unpromotedNoteExamples = unpromotedNoteAll.slice(0, 5);
|
|
3531
|
+
const unpromotedNotePaths = unpromotedNoteAll.length;
|
|
3496
3532
|
let status;
|
|
3497
3533
|
if (dirty > 0) {
|
|
3498
3534
|
status = "dirty";
|
|
@@ -3508,6 +3544,7 @@ function runSyncStatus(input) {
|
|
|
3508
3544
|
`dirty: ${dirty}`,
|
|
3509
3545
|
`ahead: ${ahead}`,
|
|
3510
3546
|
`behind: ${behind}`,
|
|
3547
|
+
`unpromoted_note_paths: ${unpromotedNotePaths}`,
|
|
3511
3548
|
`last_commit: ${last_commit}`
|
|
3512
3549
|
];
|
|
3513
3550
|
const exitCode = status === "clean" ? ExitCode.OK : ExitCode.LINT_HAS_WARNINGS;
|
|
@@ -3520,6 +3557,8 @@ function runSyncStatus(input) {
|
|
|
3520
3557
|
dirty,
|
|
3521
3558
|
ahead,
|
|
3522
3559
|
behind,
|
|
3560
|
+
unpromoted_note_paths: unpromotedNotePaths,
|
|
3561
|
+
unpromoted_note_examples: unpromotedNoteExamples,
|
|
3523
3562
|
last_commit,
|
|
3524
3563
|
status,
|
|
3525
3564
|
humanHint: hintLines.join("\n")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.37",
|
|
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
|
@@ -216,9 +216,10 @@ git fetch origin main
|
|
|
216
216
|
git reset --hard origin/main
|
|
217
217
|
bash ~/.hermes/scripts/wiki-snapshot.sh # Re-sync fresh
|
|
218
218
|
```
|
|
219
|
-
**Prevention**: Avoid editing the GitHub repo directly via web interface or uncoordinated clones. The canonical flow is:
|
|
220
|
-
- Server: rclone mount → rsync → git commit → git push
|
|
221
|
-
- macOS/desktop:
|
|
219
|
+
**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): rclone mount → rsync → git commit "Snapshot ..." → git push — **sole git writer to `main`**
|
|
221
|
+
- 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
|
+
- `wiki-sync` skill push is for **explicit** agent/human edit commits only, not automated background pushes
|
|
222
223
|
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.
|
|
223
224
|
3. **Golden Rule violation**: Never mix sync methods on the same vault. If using rclone mount + git snapshotting, do NOT also enable Obsidian Sync, Syncthing, or iCloud on `~/wiki`. The rclone mount IS the sync mechanism.
|
|
224
225
|
4. **Credential exposure**: The rclone mount and git remote use different credentials. Ensure git credentials are cached or use HTTPS with token, but never commit rclone config to git.
|
|
@@ -216,9 +216,10 @@ git fetch origin main
|
|
|
216
216
|
git reset --hard origin/main
|
|
217
217
|
bash ~/.hermes/scripts/wiki-snapshot.sh # Re-sync fresh
|
|
218
218
|
```
|
|
219
|
-
**Prevention**: Avoid editing the GitHub repo directly via web interface or uncoordinated clones. The canonical flow is:
|
|
220
|
-
- Server: rclone mount → rsync → git commit → git push
|
|
221
|
-
- macOS/desktop:
|
|
219
|
+
**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): rclone mount → rsync → git commit "Snapshot ..." → git push — **sole git writer to `main`**
|
|
221
|
+
- 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
|
+
- `wiki-sync` skill push is for **explicit** agent/human edit commits only, not automated background pushes
|
|
222
223
|
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.
|
|
223
224
|
3. **Golden Rule violation**: Never mix sync methods on the same vault. If using rclone mount + git snapshotting, do NOT also enable Obsidian Sync, Syncthing, or iCloud on `~/wiki`. The rclone mount IS the sync mechanism.
|
|
224
225
|
4. **Credential exposure**: The rclone mount and git remote use different credentials. Ensure git credentials are cached or use HTTPS with token, but never commit rclone config to git.
|