skillwiki 0.10.51 → 0.10.53
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-3IBRZTLF.js → chunk-NPHWECWR.js} +152 -65
- package/dist/{chunk-UPQ6XJSV.js → chunk-TZXWZ75D.js} +136 -46
- package/dist/cli.js +8 -15
- package/dist/managed-write-preflight-SERVDSY6.js +20 -0
- package/dist/skillwiki-mcp.js +2 -2
- 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/dist/managed-write-preflight-7GDFRPUT.js +0 -12
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
snapshotterAliasForLocalHost,
|
|
36
36
|
toUndirectedWeighted,
|
|
37
37
|
writeDotenv
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-TZXWZ75D.js";
|
|
39
39
|
import {
|
|
40
40
|
atomicWriteText,
|
|
41
41
|
prepareTypedPage
|
|
@@ -2673,6 +2673,30 @@ import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
|
|
|
2673
2673
|
import { join as join15 } from "path";
|
|
2674
2674
|
import { execSync as execSync5 } from "child_process";
|
|
2675
2675
|
import { platform as platform3 } from "os";
|
|
2676
|
+
function readPushResultState(stateFile) {
|
|
2677
|
+
if (!existsSync12(stateFile)) return { exists: false };
|
|
2678
|
+
try {
|
|
2679
|
+
const content = readFileSync7(stateFile, "utf8");
|
|
2680
|
+
let result;
|
|
2681
|
+
let reason;
|
|
2682
|
+
let timestamp;
|
|
2683
|
+
for (const line of content.split(/\r?\n/)) {
|
|
2684
|
+
const trimmed = line.trim();
|
|
2685
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
2686
|
+
const eq = trimmed.indexOf("=");
|
|
2687
|
+
if (eq <= 0) continue;
|
|
2688
|
+
const k = trimmed.slice(0, eq).trim();
|
|
2689
|
+
const v = trimmed.slice(eq + 1).trim();
|
|
2690
|
+
if (k === "result") result = v;
|
|
2691
|
+
else if (k === "reason") reason = v;
|
|
2692
|
+
else if (k === "timestamp") timestamp = v;
|
|
2693
|
+
}
|
|
2694
|
+
const malformed = result !== "ok" && result !== "refused";
|
|
2695
|
+
return { exists: true, result, reason, timestamp, malformed };
|
|
2696
|
+
} catch {
|
|
2697
|
+
return { exists: true, malformed: true };
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2676
2700
|
function readVaultSyncConfig(home) {
|
|
2677
2701
|
try {
|
|
2678
2702
|
const content = readFileSync7(join15(home, ".skillwiki", ".env"), "utf8");
|
|
@@ -2749,6 +2773,86 @@ function ageMinutes(nowMs, tsMs) {
|
|
|
2749
2773
|
if (tsMs == null) return null;
|
|
2750
2774
|
return Math.floor((nowMs - tsMs) / 6e4);
|
|
2751
2775
|
}
|
|
2776
|
+
function checkPushAgeFromTimestamp(ts) {
|
|
2777
|
+
const lastPush = new Date(ts).getTime();
|
|
2778
|
+
if (isNaN(lastPush)) {
|
|
2779
|
+
return check(
|
|
2780
|
+
"warn",
|
|
2781
|
+
"vault_sync_last_push_age",
|
|
2782
|
+
"Vault sync last push recency",
|
|
2783
|
+
`Unparseable push timestamp: ${ts}`
|
|
2784
|
+
);
|
|
2785
|
+
}
|
|
2786
|
+
const ageSec = (Date.now() - lastPush) / 1e3;
|
|
2787
|
+
if (ageSec <= 180) {
|
|
2788
|
+
return check(
|
|
2789
|
+
"pass",
|
|
2790
|
+
"vault_sync_last_push_age",
|
|
2791
|
+
"Vault sync last push recency",
|
|
2792
|
+
`Last push ${ageSec.toFixed(0)}s ago`
|
|
2793
|
+
);
|
|
2794
|
+
}
|
|
2795
|
+
return check(
|
|
2796
|
+
"warn",
|
|
2797
|
+
"vault_sync_last_push_age",
|
|
2798
|
+
"Vault sync last push recency",
|
|
2799
|
+
`Last push ${Math.round(ageSec)}s ago (>3 min)`
|
|
2800
|
+
);
|
|
2801
|
+
}
|
|
2802
|
+
function checkPushAgeFromLog(logDir, logFile) {
|
|
2803
|
+
try {
|
|
2804
|
+
const logContent = readFileSync7(logFile, "utf8");
|
|
2805
|
+
const lines = logContent.trim().split("\n").filter(Boolean);
|
|
2806
|
+
if (lines.length === 0) {
|
|
2807
|
+
return check(
|
|
2808
|
+
"warn",
|
|
2809
|
+
"vault_sync_last_push_age",
|
|
2810
|
+
"Vault sync last push recency",
|
|
2811
|
+
"Log file is empty"
|
|
2812
|
+
);
|
|
2813
|
+
}
|
|
2814
|
+
const journalRe = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z) (OK push|FAIL)/;
|
|
2815
|
+
let lastLine;
|
|
2816
|
+
let match = null;
|
|
2817
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2818
|
+
match = lines[i].match(journalRe);
|
|
2819
|
+
if (match) {
|
|
2820
|
+
lastLine = lines[i];
|
|
2821
|
+
break;
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
if (!lastLine || !match) {
|
|
2825
|
+
const tail = lines[lines.length - 1];
|
|
2826
|
+
return check(
|
|
2827
|
+
"warn",
|
|
2828
|
+
"vault_sync_last_push_age",
|
|
2829
|
+
"Vault sync last push recency",
|
|
2830
|
+
`Last log entry: ${tail.slice(0, 80)}`
|
|
2831
|
+
);
|
|
2832
|
+
}
|
|
2833
|
+
if (match[2] === "FAIL") {
|
|
2834
|
+
return check(
|
|
2835
|
+
"error",
|
|
2836
|
+
"vault_sync_last_push_age",
|
|
2837
|
+
"Vault sync last push recency",
|
|
2838
|
+
`Last push failed: ${lastLine}`
|
|
2839
|
+
);
|
|
2840
|
+
}
|
|
2841
|
+
return checkPushAgeFromTimestamp(match[1]);
|
|
2842
|
+
} catch {
|
|
2843
|
+
return existsSync12(logDir) ? check(
|
|
2844
|
+
"warn",
|
|
2845
|
+
"vault_sync_last_push_age",
|
|
2846
|
+
"Vault sync last push recency",
|
|
2847
|
+
`Log file not found at ${logFile}`
|
|
2848
|
+
) : check(
|
|
2849
|
+
"error",
|
|
2850
|
+
"vault_sync_last_push_age",
|
|
2851
|
+
"Vault sync last push recency",
|
|
2852
|
+
`Log directory not found at ${logDir}`
|
|
2853
|
+
);
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2752
2856
|
function snapshotterHealthChecks(scope, logDir, env) {
|
|
2753
2857
|
const fixture = loadSnapshotFixture(env);
|
|
2754
2858
|
const cadence = fixture ? fixture.cadence_minutes : parseInt(env.VS_SNAPSHOT_CADENCE_MINUTES ?? "30", 10) || 30;
|
|
@@ -2861,6 +2965,7 @@ function vaultSyncChecks(input) {
|
|
|
2861
2965
|
skip("vault_sync_jobs_enabled", "Vault sync jobs enabled"),
|
|
2862
2966
|
skip("vault_sync_snapshot_service_result", "Vault sync snapshot service result"),
|
|
2863
2967
|
skip("vault_sync_last_push_age", "Vault sync last push recency"),
|
|
2968
|
+
skip("vault_sync_last_push_result", "Vault sync last push result"),
|
|
2864
2969
|
skip("vault_sync_snapshot_consecutive_failures", "Vault sync snapshot consecutive failures"),
|
|
2865
2970
|
skip("vault_sync_last_fetch_status", "Vault sync last fetch status"),
|
|
2866
2971
|
skip("vault_sync_filter_present", "Vault sync filter file present"),
|
|
@@ -2869,6 +2974,7 @@ function vaultSyncChecks(input) {
|
|
|
2869
2974
|
}
|
|
2870
2975
|
const isMac = os === "darwin";
|
|
2871
2976
|
const logDir = input.logDir ?? (isMac ? join15(home, "Library", "Logs") : join15(home, ".local", "state", "vault-sync", "log"));
|
|
2977
|
+
const cacheDir = input.cacheDir ?? (isMac ? join15(home, "Library", "Caches", "vault-sync") : join15(home, ".cache", "vault-sync"));
|
|
2872
2978
|
const shareDir = input.shareDir ?? (isMac ? join15(home, "Library", "Application Support", "vault-sync", "bin") : join15(home, ".local", "share", "vault-sync", "bin"));
|
|
2873
2979
|
const filterPath = input.filterPath ?? join15(home, ".config", "rclone", "wiki-push-filters.txt");
|
|
2874
2980
|
const packagedSnapshotPath = join15(shareDir, "wiki-snapshot.sh");
|
|
@@ -2979,75 +3085,56 @@ function vaultSyncChecks(input) {
|
|
|
2979
3085
|
"Scheduler check failed \u2014 run vault-sync-install"
|
|
2980
3086
|
);
|
|
2981
3087
|
}
|
|
3088
|
+
const stateFile = join15(cacheDir, "wiki-push-result.state");
|
|
3089
|
+
const pushState = readPushResultState(stateFile);
|
|
2982
3090
|
const logFile = join15(logDir, "wiki-push.log");
|
|
2983
3091
|
let c3;
|
|
2984
|
-
|
|
2985
|
-
const
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
c3 = check(
|
|
2989
|
-
"warn",
|
|
2990
|
-
"vault_sync_last_push_age",
|
|
2991
|
-
"Vault sync last push recency",
|
|
2992
|
-
"Log file is empty"
|
|
2993
|
-
);
|
|
2994
|
-
} else {
|
|
2995
|
-
const lastLine = [...lines].reverse().find((line) => /FAIL|OK push/.test(line)) ?? lines[lines.length - 1];
|
|
2996
|
-
if (/FAIL/.test(lastLine)) {
|
|
2997
|
-
c3 = check(
|
|
2998
|
-
"error",
|
|
2999
|
-
"vault_sync_last_push_age",
|
|
3000
|
-
"Vault sync last push recency",
|
|
3001
|
-
`Last push failed: ${lastLine}`
|
|
3002
|
-
);
|
|
3003
|
-
} else if (/OK push/.test(lastLine)) {
|
|
3004
|
-
const tsMatch = lastLine.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)/);
|
|
3005
|
-
if (tsMatch) {
|
|
3006
|
-
const lastPush = new Date(tsMatch[1]).getTime();
|
|
3007
|
-
const ageSec = (Date.now() - lastPush) / 1e3;
|
|
3008
|
-
if (ageSec <= 180) {
|
|
3009
|
-
c3 = check(
|
|
3010
|
-
"pass",
|
|
3011
|
-
"vault_sync_last_push_age",
|
|
3012
|
-
"Vault sync last push recency",
|
|
3013
|
-
`Last push ${ageSec.toFixed(0)}s ago`
|
|
3014
|
-
);
|
|
3015
|
-
} else {
|
|
3016
|
-
c3 = check(
|
|
3017
|
-
"warn",
|
|
3018
|
-
"vault_sync_last_push_age",
|
|
3019
|
-
"Vault sync last push recency",
|
|
3020
|
-
`Last push ${Math.round(ageSec)}s ago (>3 min)`
|
|
3021
|
-
);
|
|
3022
|
-
}
|
|
3023
|
-
} else {
|
|
3024
|
-
c3 = check(
|
|
3025
|
-
"warn",
|
|
3026
|
-
"vault_sync_last_push_age",
|
|
3027
|
-
"Vault sync last push recency",
|
|
3028
|
-
`Unparseable push line: ${lastLine.slice(0, 80)}`
|
|
3029
|
-
);
|
|
3030
|
-
}
|
|
3031
|
-
} else {
|
|
3032
|
-
c3 = check(
|
|
3033
|
-
"warn",
|
|
3034
|
-
"vault_sync_last_push_age",
|
|
3035
|
-
"Vault sync last push recency",
|
|
3036
|
-
`Last log entry: ${lastLine.slice(0, 80)}`
|
|
3037
|
-
);
|
|
3038
|
-
}
|
|
3039
|
-
}
|
|
3040
|
-
} catch {
|
|
3041
|
-
c3 = existsSync12(logDir) ? check(
|
|
3042
|
-
"warn",
|
|
3092
|
+
if (pushState.exists && !pushState.malformed && pushState.result === "refused") {
|
|
3093
|
+
const reasonSuffix = pushState.reason ? `: ${pushState.reason}` : "";
|
|
3094
|
+
c3 = check(
|
|
3095
|
+
"error",
|
|
3043
3096
|
"vault_sync_last_push_age",
|
|
3044
3097
|
"Vault sync last push recency",
|
|
3045
|
-
`
|
|
3046
|
-
)
|
|
3047
|
-
|
|
3098
|
+
`Last push refused${reasonSuffix}`
|
|
3099
|
+
);
|
|
3100
|
+
} else if (pushState.exists && !pushState.malformed && pushState.result === "ok") {
|
|
3101
|
+
c3 = pushState.timestamp ? checkPushAgeFromTimestamp(pushState.timestamp) : check(
|
|
3102
|
+
"warn",
|
|
3048
3103
|
"vault_sync_last_push_age",
|
|
3049
3104
|
"Vault sync last push recency",
|
|
3050
|
-
|
|
3105
|
+
"State file missing timestamp"
|
|
3106
|
+
);
|
|
3107
|
+
} else {
|
|
3108
|
+
c3 = checkPushAgeFromLog(logDir, logFile);
|
|
3109
|
+
}
|
|
3110
|
+
let cPushResult;
|
|
3111
|
+
if (!pushState.exists) {
|
|
3112
|
+
cPushResult = check(
|
|
3113
|
+
"warn",
|
|
3114
|
+
"vault_sync_last_push_result",
|
|
3115
|
+
"Vault sync last push result",
|
|
3116
|
+
`no push result state file (push may not have run yet): ${stateFile}`
|
|
3117
|
+
);
|
|
3118
|
+
} else if (pushState.malformed) {
|
|
3119
|
+
cPushResult = check(
|
|
3120
|
+
"warn",
|
|
3121
|
+
"vault_sync_last_push_result",
|
|
3122
|
+
"Vault sync last push result",
|
|
3123
|
+
`malformed state file: ${stateFile}`
|
|
3124
|
+
);
|
|
3125
|
+
} else if (pushState.result === "ok") {
|
|
3126
|
+
cPushResult = check(
|
|
3127
|
+
"pass",
|
|
3128
|
+
"vault_sync_last_push_result",
|
|
3129
|
+
"Vault sync last push result",
|
|
3130
|
+
`result=ok timestamp=${pushState.timestamp ?? ""}`
|
|
3131
|
+
);
|
|
3132
|
+
} else {
|
|
3133
|
+
cPushResult = check(
|
|
3134
|
+
"error",
|
|
3135
|
+
"vault_sync_last_push_result",
|
|
3136
|
+
"Vault sync last push result",
|
|
3137
|
+
`result=refused reason=${pushState.reason ?? ""} timestamp=${pushState.timestamp ?? ""}`
|
|
3051
3138
|
);
|
|
3052
3139
|
}
|
|
3053
3140
|
const fetchLogFile = join15(logDir, "wiki-fetch.log");
|
|
@@ -3182,7 +3269,7 @@ function vaultSyncChecks(input) {
|
|
|
3182
3269
|
);
|
|
3183
3270
|
}
|
|
3184
3271
|
}
|
|
3185
|
-
return [c1, c2, c3, cFetch, c4, c5];
|
|
3272
|
+
return [c1, c2, c3, cPushResult, cFetch, c4, c5];
|
|
3186
3273
|
}
|
|
3187
3274
|
function checkVaultSyncPullHelper(home, env) {
|
|
3188
3275
|
const path = resolveVaultSyncPullHelper({
|
|
@@ -607,7 +607,7 @@ function safeUserName() {
|
|
|
607
607
|
// src/commands/sync.ts
|
|
608
608
|
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
609
609
|
import { join as join17 } from "path";
|
|
610
|
-
import { execFileSync as
|
|
610
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
611
611
|
|
|
612
612
|
// src/utils/last-op.ts
|
|
613
613
|
import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from "fs";
|
|
@@ -5037,6 +5037,41 @@ var LINT_RULES = [
|
|
|
5037
5037
|
cycleTrapsRule
|
|
5038
5038
|
];
|
|
5039
5039
|
|
|
5040
|
+
// src/utils/git-archive.ts
|
|
5041
|
+
import { execFileSync } from "child_process";
|
|
5042
|
+
import { rmSync } from "fs";
|
|
5043
|
+
function extractGitTree(vault, ref, destDir) {
|
|
5044
|
+
if (process.platform === "win32") {
|
|
5045
|
+
const zipPath = `${destDir}.zip`;
|
|
5046
|
+
execFileSync("git", ["archive", "--format=zip", `--output=${zipPath}`, ref], {
|
|
5047
|
+
cwd: vault,
|
|
5048
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5049
|
+
});
|
|
5050
|
+
try {
|
|
5051
|
+
execFileSync("tar", ["-xf", zipPath], {
|
|
5052
|
+
cwd: destDir,
|
|
5053
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5054
|
+
});
|
|
5055
|
+
} finally {
|
|
5056
|
+
try {
|
|
5057
|
+
rmSync(zipPath, { force: true });
|
|
5058
|
+
} catch {
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5061
|
+
return;
|
|
5062
|
+
}
|
|
5063
|
+
const archive = execFileSync("git", ["archive", "--format=tar", ref], {
|
|
5064
|
+
cwd: vault,
|
|
5065
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
5066
|
+
maxBuffer: 256 * 1024 * 1024
|
|
5067
|
+
});
|
|
5068
|
+
execFileSync("tar", ["-xf", "-"], {
|
|
5069
|
+
cwd: destDir,
|
|
5070
|
+
input: archive,
|
|
5071
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5072
|
+
});
|
|
5073
|
+
}
|
|
5074
|
+
|
|
5040
5075
|
// src/lint/runner.ts
|
|
5041
5076
|
var LintRunner = class {
|
|
5042
5077
|
rules;
|
|
@@ -5183,10 +5218,10 @@ function runLint(input) {
|
|
|
5183
5218
|
return defaultLintRunner.run(input);
|
|
5184
5219
|
}
|
|
5185
5220
|
async function runSyncLintDelta(input) {
|
|
5186
|
-
const { mkdtempSync, rmSync, existsSync: fsExists } = await import("fs");
|
|
5221
|
+
const { mkdtempSync, rmSync: rmSync2, existsSync: fsExists } = await import("fs");
|
|
5187
5222
|
const { join: pathJoin } = await import("path");
|
|
5188
5223
|
const { tmpdir } = await import("os");
|
|
5189
|
-
const { execFileSync:
|
|
5224
|
+
const { execFileSync: execFileSync5 } = await import("child_process");
|
|
5190
5225
|
const vault = input.vault;
|
|
5191
5226
|
const baseRef = input.baseRef ?? "origin/main";
|
|
5192
5227
|
const days = input.days ?? 90;
|
|
@@ -5199,7 +5234,7 @@ async function runSyncLintDelta(input) {
|
|
|
5199
5234
|
};
|
|
5200
5235
|
}
|
|
5201
5236
|
try {
|
|
5202
|
-
|
|
5237
|
+
execFileSync5("git", ["rev-parse", "--verify", baseRef], {
|
|
5203
5238
|
cwd: vault,
|
|
5204
5239
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5205
5240
|
});
|
|
@@ -5229,16 +5264,7 @@ async function runSyncLintDelta(input) {
|
|
|
5229
5264
|
const fullFps = collectLintErrorFingerprints(fullOutput);
|
|
5230
5265
|
const tmpRoot = mkdtempSync(pathJoin(tmpdir(), "skillwiki-lint-delta-"));
|
|
5231
5266
|
try {
|
|
5232
|
-
|
|
5233
|
-
cwd: vault,
|
|
5234
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
5235
|
-
maxBuffer: 256 * 1024 * 1024
|
|
5236
|
-
});
|
|
5237
|
-
execFileSync4("tar", ["-xf", "-"], {
|
|
5238
|
-
cwd: tmpRoot,
|
|
5239
|
-
input: archive,
|
|
5240
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
5241
|
-
});
|
|
5267
|
+
extractGitTree(vault, baseRef, tmpRoot);
|
|
5242
5268
|
if (!fsExists(pathJoin(tmpRoot, "SCHEMA.md"))) {
|
|
5243
5269
|
}
|
|
5244
5270
|
const baseLint = await runLint({ vault: tmpRoot, days, lines, logThreshold });
|
|
@@ -5293,23 +5319,23 @@ async function runSyncLintDelta(input) {
|
|
|
5293
5319
|
};
|
|
5294
5320
|
} finally {
|
|
5295
5321
|
try {
|
|
5296
|
-
|
|
5322
|
+
rmSync2(tmpRoot, { recursive: true, force: true });
|
|
5297
5323
|
} catch {
|
|
5298
5324
|
}
|
|
5299
5325
|
}
|
|
5300
5326
|
}
|
|
5301
5327
|
|
|
5302
5328
|
// src/utils/git.ts
|
|
5303
|
-
import { execFileSync } from "child_process";
|
|
5329
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
5304
5330
|
function git(cwd, args) {
|
|
5305
5331
|
try {
|
|
5306
|
-
return
|
|
5332
|
+
return execFileSync2("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
5307
5333
|
} catch {
|
|
5308
5334
|
return "";
|
|
5309
5335
|
}
|
|
5310
5336
|
}
|
|
5311
5337
|
function gitStrict(cwd, args) {
|
|
5312
|
-
return
|
|
5338
|
+
return execFileSync2("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
5313
5339
|
}
|
|
5314
5340
|
|
|
5315
5341
|
// src/utils/sync-lock.ts
|
|
@@ -5494,9 +5520,9 @@ function stageVaultContentChanges(vault) {
|
|
|
5494
5520
|
// src/utils/remote-health.ts
|
|
5495
5521
|
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
5496
5522
|
import { join as join15 } from "path";
|
|
5497
|
-
import { execFileSync as
|
|
5523
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
5498
5524
|
var REMOTE_PROBE_TIMEOUT_MS = 3e3;
|
|
5499
|
-
var defaultExec = (file, args, cwd) =>
|
|
5525
|
+
var defaultExec = (file, args, cwd) => execFileSync3(file, args, {
|
|
5500
5526
|
cwd,
|
|
5501
5527
|
encoding: "utf8",
|
|
5502
5528
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -5716,7 +5742,7 @@ function isTrackedNotePath(path) {
|
|
|
5716
5742
|
}
|
|
5717
5743
|
function refHasPath(vault, ref, path) {
|
|
5718
5744
|
try {
|
|
5719
|
-
|
|
5745
|
+
execFileSync4("git", ["cat-file", "-e", `${ref}:${path}`], {
|
|
5720
5746
|
cwd: vault,
|
|
5721
5747
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5722
5748
|
});
|
|
@@ -6103,6 +6129,7 @@ function collectManagedWriterAncestorPids(startPid, readStatus = readProcStatus)
|
|
|
6103
6129
|
return ids;
|
|
6104
6130
|
}
|
|
6105
6131
|
function readProcStatus(pid) {
|
|
6132
|
+
if (process.platform !== "linux") return null;
|
|
6106
6133
|
try {
|
|
6107
6134
|
return readFileSync5(`/proc/${pid}/status`, "utf8");
|
|
6108
6135
|
} catch {
|
|
@@ -6145,12 +6172,12 @@ function classifyManagedWriterProcesses(snapshot, currentPid = process.pid, ance
|
|
|
6145
6172
|
function managedWriterSnapshot() {
|
|
6146
6173
|
try {
|
|
6147
6174
|
if (process.platform === "win32") {
|
|
6148
|
-
return
|
|
6175
|
+
return execFileSync4("tasklist", ["/FO", "CSV", "/NH"], {
|
|
6149
6176
|
encoding: "utf8",
|
|
6150
6177
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6151
6178
|
});
|
|
6152
6179
|
}
|
|
6153
|
-
return
|
|
6180
|
+
return execFileSync4("ps", ["-axo", "pid=,command="], {
|
|
6154
6181
|
encoding: "utf8",
|
|
6155
6182
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6156
6183
|
});
|
|
@@ -6688,10 +6715,25 @@ function resolveConfiguredSnapshotWorktree(home) {
|
|
|
6688
6715
|
}
|
|
6689
6716
|
|
|
6690
6717
|
// src/utils/managed-write-preflight.ts
|
|
6718
|
+
var DEFAULT_MANAGED_WRITE_WAIT_MS = 24e4;
|
|
6719
|
+
var MANAGED_WRITE_POLL_INTERVAL_MS = 2e3;
|
|
6720
|
+
function resolveManagedWriteWaitMs(env) {
|
|
6721
|
+
const raw = env?.SKILLWIKI_MANAGED_WRITE_WAIT_MS ?? process.env.SKILLWIKI_MANAGED_WRITE_WAIT_MS;
|
|
6722
|
+
if (!raw) return DEFAULT_MANAGED_WRITE_WAIT_MS;
|
|
6723
|
+
const parsed = Number.parseInt(raw, 10);
|
|
6724
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_MANAGED_WRITE_WAIT_MS;
|
|
6725
|
+
return parsed;
|
|
6726
|
+
}
|
|
6691
6727
|
var DEFAULT_DEPS = {
|
|
6692
6728
|
converge: (input) => runVaultSyncPullHelper(input),
|
|
6693
6729
|
resolveConfiguredSnapshotWorktree,
|
|
6694
|
-
syncPeers: runSyncPeers
|
|
6730
|
+
syncPeers: runSyncPeers,
|
|
6731
|
+
sleepMs: (ms) => new Promise((resolve7) => setTimeout(resolve7, ms)),
|
|
6732
|
+
nowMs: () => Date.now(),
|
|
6733
|
+
logHeartbeat: (message) => {
|
|
6734
|
+
process.stderr.write(`${message}
|
|
6735
|
+
`);
|
|
6736
|
+
}
|
|
6695
6737
|
};
|
|
6696
6738
|
var SAFE_MANAGED_WRITER_KINDS = new Set(MANAGED_WRITER_KINDS);
|
|
6697
6739
|
var SAFE_STASH_AUDIT_CLASSIFICATIONS = new Set(STASH_AUDIT_CLASSIFICATIONS);
|
|
@@ -6764,48 +6806,91 @@ function peerCheckFailure(reason, detail = {}) {
|
|
|
6764
6806
|
result: err("PREFLIGHT_FAILED", { reason, ...detail })
|
|
6765
6807
|
};
|
|
6766
6808
|
}
|
|
6767
|
-
function
|
|
6809
|
+
function evaluateManagedWritePeerGate(vault, mode, deps) {
|
|
6768
6810
|
try {
|
|
6769
6811
|
const check = (deps.syncPeers ?? DEFAULT_DEPS.syncPeers)({ vault });
|
|
6770
6812
|
if (check.exitCode !== ExitCode.OK || !check.result.ok) {
|
|
6771
|
-
return peerCheckFailure("peer-check-failed");
|
|
6813
|
+
return { status: "block", failure: peerCheckFailure("peer-check-failed") };
|
|
6772
6814
|
}
|
|
6773
6815
|
const validated = validateSyncPeersOutput(check.result.data);
|
|
6774
6816
|
if (!validated) {
|
|
6775
|
-
return peerCheckFailure("peer-check-failed");
|
|
6817
|
+
return { status: "block", failure: peerCheckFailure("peer-check-failed") };
|
|
6776
6818
|
}
|
|
6777
6819
|
const { output: peerOutput, foreignLockCount, recentPeerStashCount } = validated;
|
|
6778
6820
|
const nonWriterBlockingSignal = foreignLockCount > 0 || recentPeerStashCount > 0;
|
|
6779
6821
|
const writerOnly = peerOutput.managed_writers.blocking && !nonWriterBlockingSignal;
|
|
6780
|
-
if (mode !== "git-writer" && writerOnly) return
|
|
6822
|
+
if (mode !== "git-writer" && writerOnly) return { status: "pass" };
|
|
6781
6823
|
const managedWriterBlocking = mode === "git-writer" && peerOutput.managed_writers.blocking;
|
|
6782
6824
|
const hasKnownBlockingSignal = foreignLockCount > 0 || managedWriterBlocking || recentPeerStashCount > 0;
|
|
6783
6825
|
if (!peerOutput.blocking) {
|
|
6784
|
-
return hasKnownBlockingSignal ? peerCheckFailure("peer-check-failed") :
|
|
6826
|
+
return hasKnownBlockingSignal ? { status: "block", failure: peerCheckFailure("peer-check-failed") } : { status: "pass" };
|
|
6785
6827
|
}
|
|
6786
6828
|
if (managedWriterBlocking) {
|
|
6787
|
-
return
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
}
|
|
6829
|
+
return {
|
|
6830
|
+
status: "overlap",
|
|
6831
|
+
count: peerOutput.managed_writers.count,
|
|
6832
|
+
kinds: peerOutput.managed_writers.kinds.slice(0, 8)
|
|
6833
|
+
};
|
|
6792
6834
|
}
|
|
6793
6835
|
if (foreignLockCount > 0) {
|
|
6794
|
-
return
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6836
|
+
return {
|
|
6837
|
+
status: "block",
|
|
6838
|
+
failure: peerCheckFailure("peer-lock", {
|
|
6839
|
+
foreign_lock_count: foreignLockCount,
|
|
6840
|
+
blocking: true
|
|
6841
|
+
})
|
|
6842
|
+
};
|
|
6798
6843
|
}
|
|
6799
6844
|
if (recentPeerStashCount > 0) {
|
|
6800
|
-
return
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6845
|
+
return {
|
|
6846
|
+
status: "block",
|
|
6847
|
+
failure: peerCheckFailure("recent-peer-stash", {
|
|
6848
|
+
recent_peer_stash_count: recentPeerStashCount,
|
|
6849
|
+
stash_classification: "recent_known_peer_stash",
|
|
6850
|
+
blocking: true
|
|
6851
|
+
})
|
|
6852
|
+
};
|
|
6805
6853
|
}
|
|
6806
|
-
return
|
|
6854
|
+
return {
|
|
6855
|
+
status: "block",
|
|
6856
|
+
failure: peerCheckFailure("peer-blocked", { blocking: true })
|
|
6857
|
+
};
|
|
6807
6858
|
} catch {
|
|
6808
|
-
return peerCheckFailure("peer-check-failed");
|
|
6859
|
+
return { status: "block", failure: peerCheckFailure("peer-check-failed") };
|
|
6860
|
+
}
|
|
6861
|
+
}
|
|
6862
|
+
async function runManagedWritePeerGate(vault, mode, deps = DEFAULT_DEPS, env) {
|
|
6863
|
+
const now = deps.nowMs ?? DEFAULT_DEPS.nowMs;
|
|
6864
|
+
const sleep = deps.sleepMs ?? DEFAULT_DEPS.sleepMs;
|
|
6865
|
+
const logHeartbeat = deps.logHeartbeat ?? DEFAULT_DEPS.logHeartbeat;
|
|
6866
|
+
const waitMs = resolveManagedWriteWaitMs(env);
|
|
6867
|
+
const initial = evaluateManagedWritePeerGate(vault, mode, deps);
|
|
6868
|
+
if (initial.status === "pass") return null;
|
|
6869
|
+
if (initial.status === "block") return initial.failure;
|
|
6870
|
+
const startedAt = now();
|
|
6871
|
+
const deadline = startedAt + waitMs;
|
|
6872
|
+
let lastOverlap = initial;
|
|
6873
|
+
for (; ; ) {
|
|
6874
|
+
const t = now();
|
|
6875
|
+
const elapsed = Math.max(0, t - startedAt);
|
|
6876
|
+
const remainingMs = Math.max(0, deadline - t);
|
|
6877
|
+
const remainingSec = Math.ceil(remainingMs / 1e3);
|
|
6878
|
+
const writerKindDesc = lastOverlap.kinds.length > 0 ? lastOverlap.kinds.join(", ") : "unknown";
|
|
6879
|
+
logHeartbeat(`skillwiki: waiting for live vault writer (${writerKindDesc}), ${remainingSec}s left`);
|
|
6880
|
+
if (t >= deadline) {
|
|
6881
|
+
return peerCheckFailure("live-writer-overlap", {
|
|
6882
|
+
managed_writer_count: lastOverlap.count,
|
|
6883
|
+
managed_writer_kinds: lastOverlap.kinds,
|
|
6884
|
+
blocking: true,
|
|
6885
|
+
waited_ms: elapsed
|
|
6886
|
+
});
|
|
6887
|
+
}
|
|
6888
|
+
const nextSleepMs = Math.min(MANAGED_WRITE_POLL_INTERVAL_MS, remainingMs);
|
|
6889
|
+
await sleep(nextSleepMs);
|
|
6890
|
+
const check = evaluateManagedWritePeerGate(vault, mode, deps);
|
|
6891
|
+
if (check.status === "pass") return null;
|
|
6892
|
+
if (check.status === "block") return check.failure;
|
|
6893
|
+
lastOverlap = check;
|
|
6809
6894
|
}
|
|
6810
6895
|
}
|
|
6811
6896
|
function preflightBlocker(vault) {
|
|
@@ -7081,7 +7166,7 @@ async function runManagedWriteTransaction(input, deps = DEFAULT_DEPS) {
|
|
|
7081
7166
|
})
|
|
7082
7167
|
};
|
|
7083
7168
|
}
|
|
7084
|
-
const peerGate = runManagedWritePeerGate(mutationVault, receipt.mode, deps);
|
|
7169
|
+
const peerGate = await runManagedWritePeerGate(mutationVault, receipt.mode, deps, input.env);
|
|
7085
7170
|
if (peerGate) return peerGate;
|
|
7086
7171
|
return await input.mutate(receipt);
|
|
7087
7172
|
} finally {
|
|
@@ -7103,6 +7188,7 @@ export {
|
|
|
7103
7188
|
louvain,
|
|
7104
7189
|
communityCohesion,
|
|
7105
7190
|
extractIssuePage,
|
|
7191
|
+
extractGitTree,
|
|
7106
7192
|
runLinks,
|
|
7107
7193
|
extractTaxonomy,
|
|
7108
7194
|
taxonomyCommentForPage,
|
|
@@ -7180,6 +7266,10 @@ export {
|
|
|
7180
7266
|
markJournalSuperseded,
|
|
7181
7267
|
supersedeStaleReviewRequiredJournals,
|
|
7182
7268
|
resolveConfiguredSnapshotWorktree,
|
|
7269
|
+
DEFAULT_MANAGED_WRITE_WAIT_MS,
|
|
7270
|
+
MANAGED_WRITE_POLL_INTERVAL_MS,
|
|
7271
|
+
resolveManagedWriteWaitMs,
|
|
7272
|
+
runManagedWritePeerGate,
|
|
7183
7273
|
runManagedWritePreflight,
|
|
7184
7274
|
runManagedWriteTransaction
|
|
7185
7275
|
};
|
package/dist/cli.js
CHANGED
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
snapshotterHealthChecks,
|
|
51
51
|
upsertIndexEntry,
|
|
52
52
|
vectorIndexStatus
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-NPHWECWR.js";
|
|
54
54
|
import {
|
|
55
55
|
normalizeDistTag,
|
|
56
56
|
readCache,
|
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
collectClaimedTranscripts,
|
|
80
80
|
defaultLintRunner,
|
|
81
81
|
extractBodyWikilinks,
|
|
82
|
+
extractGitTree,
|
|
82
83
|
extractIssuePage,
|
|
83
84
|
extractTaxonomy,
|
|
84
85
|
getCliSessionId,
|
|
@@ -145,7 +146,7 @@ import {
|
|
|
145
146
|
supersedeStaleReviewRequiredJournals,
|
|
146
147
|
taxonomyCommentForPage,
|
|
147
148
|
writeDotenv
|
|
148
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-TZXWZ75D.js";
|
|
149
150
|
import {
|
|
150
151
|
assertTargetInsideVault,
|
|
151
152
|
atomicWriteText,
|
|
@@ -549,16 +550,7 @@ async function runEval(input) {
|
|
|
549
550
|
}
|
|
550
551
|
const tmpRoot = mkdtempSync(join2(tmpdir(), "skillwiki-eval-delta-"));
|
|
551
552
|
try {
|
|
552
|
-
|
|
553
|
-
cwd: vaultPath,
|
|
554
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
555
|
-
maxBuffer: 256 * 1024 * 1024
|
|
556
|
-
});
|
|
557
|
-
execFileSync("tar", ["-xf", "-"], {
|
|
558
|
-
cwd: tmpRoot,
|
|
559
|
-
input: archive,
|
|
560
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
561
|
-
});
|
|
553
|
+
extractGitTree(vaultPath, baseRef, tmpRoot);
|
|
562
554
|
const baseAggRes = await aggregateVault(tmpRoot, topLimit);
|
|
563
555
|
if (!baseAggRes.ok) {
|
|
564
556
|
return {
|
|
@@ -3049,11 +3041,12 @@ function classifyLog(path, id, label, okPattern) {
|
|
|
3049
3041
|
if (!existsSync6(path)) return { id, label, status: "warn", detail: `log file missing: ${path}` };
|
|
3050
3042
|
const lines = readFileSync10(path, "utf8").split(/\r?\n/).filter(Boolean);
|
|
3051
3043
|
if (lines.length === 0) return { id, label, status: "warn", detail: `log file empty: ${path}` };
|
|
3044
|
+
const journalFailRe = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z (FAIL|ERROR)\b/;
|
|
3052
3045
|
const statusLine = [...lines].reverse().find(
|
|
3053
|
-
(line) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z /.test(line) && (okPattern.test(line) ||
|
|
3046
|
+
(line) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z /.test(line) && (okPattern.test(line) || journalFailRe.test(line))
|
|
3054
3047
|
);
|
|
3055
3048
|
const last = statusLine ?? lines[lines.length - 1];
|
|
3056
|
-
if (
|
|
3049
|
+
if (journalFailRe.test(last)) return { id, label, status: "error", detail: last.slice(0, 120) };
|
|
3057
3050
|
if (okPattern.test(last)) return { id, label, status: "pass", detail: last.slice(0, 120) };
|
|
3058
3051
|
return { id, label, status: "warn", detail: last.slice(0, 120) };
|
|
3059
3052
|
}
|
|
@@ -10076,7 +10069,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
|
|
|
10076
10069
|
if (dirty) {
|
|
10077
10070
|
return emit(dirty, void 0, { postCommit: false });
|
|
10078
10071
|
}
|
|
10079
|
-
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-
|
|
10072
|
+
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-SERVDSY6.js");
|
|
10080
10073
|
const run = await runManagedWriteTransaction2({
|
|
10081
10074
|
vault,
|
|
10082
10075
|
command,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_MANAGED_WRITE_WAIT_MS,
|
|
4
|
+
MANAGED_WRITE_POLL_INTERVAL_MS,
|
|
5
|
+
resolveManagedWriteWaitMs,
|
|
6
|
+
runManagedWritePeerGate,
|
|
7
|
+
runManagedWritePreflight,
|
|
8
|
+
runManagedWriteTransaction
|
|
9
|
+
} from "./chunk-TZXWZ75D.js";
|
|
10
|
+
import "./chunk-74OSLCXE.js";
|
|
11
|
+
import "./chunk-GAHMWLWU.js";
|
|
12
|
+
import "./chunk-IJ7DD7QZ.js";
|
|
13
|
+
export {
|
|
14
|
+
DEFAULT_MANAGED_WRITE_WAIT_MS,
|
|
15
|
+
MANAGED_WRITE_POLL_INTERVAL_MS,
|
|
16
|
+
resolveManagedWriteWaitMs,
|
|
17
|
+
runManagedWritePeerGate,
|
|
18
|
+
runManagedWritePreflight,
|
|
19
|
+
runManagedWriteTransaction
|
|
20
|
+
};
|
package/dist/skillwiki-mcp.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runSkillwikiMcpStdio
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NPHWECWR.js";
|
|
5
5
|
import "./chunk-7I2TPIV5.js";
|
|
6
6
|
import "./chunk-O3HCB7R2.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-TZXWZ75D.js";
|
|
8
8
|
import "./chunk-74OSLCXE.js";
|
|
9
9
|
import "./chunk-HBQTTYXZ.js";
|
|
10
10
|
import "./chunk-GAHMWLWU.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.53",
|
|
4
4
|
"skills": "./",
|
|
5
5
|
"description": "Project-aware Karpathy-style knowledge base for Claude Code: 20 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI.",
|
|
6
6
|
"author": {
|
package/skills/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
runManagedWritePreflight,
|
|
4
|
-
runManagedWriteTransaction
|
|
5
|
-
} from "./chunk-UPQ6XJSV.js";
|
|
6
|
-
import "./chunk-74OSLCXE.js";
|
|
7
|
-
import "./chunk-GAHMWLWU.js";
|
|
8
|
-
import "./chunk-IJ7DD7QZ.js";
|
|
9
|
-
export {
|
|
10
|
-
runManagedWritePreflight,
|
|
11
|
-
runManagedWriteTransaction
|
|
12
|
-
};
|