skillwiki 0.10.52 → 0.10.54
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-VRK5DOC5.js → chunk-EHUFPORA.js} +86 -23
- package/dist/{chunk-JTAZUR2W.js → chunk-Q23OSECM.js} +157 -66
- package/dist/cli.js +43 -12
- package/dist/managed-write-preflight-CMVCRXRG.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-WIW5L22Q.js +0 -12
|
@@ -6715,10 +6715,25 @@ function resolveConfiguredSnapshotWorktree(home) {
|
|
|
6715
6715
|
}
|
|
6716
6716
|
|
|
6717
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
|
+
}
|
|
6718
6727
|
var DEFAULT_DEPS = {
|
|
6719
6728
|
converge: (input) => runVaultSyncPullHelper(input),
|
|
6720
6729
|
resolveConfiguredSnapshotWorktree,
|
|
6721
|
-
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
|
+
}
|
|
6722
6737
|
};
|
|
6723
6738
|
var SAFE_MANAGED_WRITER_KINDS = new Set(MANAGED_WRITER_KINDS);
|
|
6724
6739
|
var SAFE_STASH_AUDIT_CLASSIFICATIONS = new Set(STASH_AUDIT_CLASSIFICATIONS);
|
|
@@ -6791,48 +6806,91 @@ function peerCheckFailure(reason, detail = {}) {
|
|
|
6791
6806
|
result: err("PREFLIGHT_FAILED", { reason, ...detail })
|
|
6792
6807
|
};
|
|
6793
6808
|
}
|
|
6794
|
-
function
|
|
6809
|
+
function evaluateManagedWritePeerGate(vault, mode, deps) {
|
|
6795
6810
|
try {
|
|
6796
6811
|
const check = (deps.syncPeers ?? DEFAULT_DEPS.syncPeers)({ vault });
|
|
6797
6812
|
if (check.exitCode !== ExitCode.OK || !check.result.ok) {
|
|
6798
|
-
return peerCheckFailure("peer-check-failed");
|
|
6813
|
+
return { status: "block", failure: peerCheckFailure("peer-check-failed") };
|
|
6799
6814
|
}
|
|
6800
6815
|
const validated = validateSyncPeersOutput(check.result.data);
|
|
6801
6816
|
if (!validated) {
|
|
6802
|
-
return peerCheckFailure("peer-check-failed");
|
|
6817
|
+
return { status: "block", failure: peerCheckFailure("peer-check-failed") };
|
|
6803
6818
|
}
|
|
6804
6819
|
const { output: peerOutput, foreignLockCount, recentPeerStashCount } = validated;
|
|
6805
6820
|
const nonWriterBlockingSignal = foreignLockCount > 0 || recentPeerStashCount > 0;
|
|
6806
6821
|
const writerOnly = peerOutput.managed_writers.blocking && !nonWriterBlockingSignal;
|
|
6807
|
-
if (mode !== "git-writer" && writerOnly) return
|
|
6822
|
+
if (mode !== "git-writer" && writerOnly) return { status: "pass" };
|
|
6808
6823
|
const managedWriterBlocking = mode === "git-writer" && peerOutput.managed_writers.blocking;
|
|
6809
6824
|
const hasKnownBlockingSignal = foreignLockCount > 0 || managedWriterBlocking || recentPeerStashCount > 0;
|
|
6810
6825
|
if (!peerOutput.blocking) {
|
|
6811
|
-
return hasKnownBlockingSignal ? peerCheckFailure("peer-check-failed") :
|
|
6826
|
+
return hasKnownBlockingSignal ? { status: "block", failure: peerCheckFailure("peer-check-failed") } : { status: "pass" };
|
|
6812
6827
|
}
|
|
6813
6828
|
if (managedWriterBlocking) {
|
|
6814
|
-
return
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
}
|
|
6829
|
+
return {
|
|
6830
|
+
status: "overlap",
|
|
6831
|
+
count: peerOutput.managed_writers.count,
|
|
6832
|
+
kinds: peerOutput.managed_writers.kinds.slice(0, 8)
|
|
6833
|
+
};
|
|
6819
6834
|
}
|
|
6820
6835
|
if (foreignLockCount > 0) {
|
|
6821
|
-
return
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6836
|
+
return {
|
|
6837
|
+
status: "block",
|
|
6838
|
+
failure: peerCheckFailure("peer-lock", {
|
|
6839
|
+
foreign_lock_count: foreignLockCount,
|
|
6840
|
+
blocking: true
|
|
6841
|
+
})
|
|
6842
|
+
};
|
|
6825
6843
|
}
|
|
6826
6844
|
if (recentPeerStashCount > 0) {
|
|
6827
|
-
return
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
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
|
+
};
|
|
6832
6853
|
}
|
|
6833
|
-
return
|
|
6854
|
+
return {
|
|
6855
|
+
status: "block",
|
|
6856
|
+
failure: peerCheckFailure("peer-blocked", { blocking: true })
|
|
6857
|
+
};
|
|
6834
6858
|
} catch {
|
|
6835
|
-
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;
|
|
6836
6894
|
}
|
|
6837
6895
|
}
|
|
6838
6896
|
function preflightBlocker(vault) {
|
|
@@ -7108,7 +7166,7 @@ async function runManagedWriteTransaction(input, deps = DEFAULT_DEPS) {
|
|
|
7108
7166
|
})
|
|
7109
7167
|
};
|
|
7110
7168
|
}
|
|
7111
|
-
const peerGate = runManagedWritePeerGate(mutationVault, receipt.mode, deps);
|
|
7169
|
+
const peerGate = await runManagedWritePeerGate(mutationVault, receipt.mode, deps, input.env);
|
|
7112
7170
|
if (peerGate) return peerGate;
|
|
7113
7171
|
return await input.mutate(receipt);
|
|
7114
7172
|
} finally {
|
|
@@ -7183,6 +7241,7 @@ export {
|
|
|
7183
7241
|
resolveFleetHostId,
|
|
7184
7242
|
git,
|
|
7185
7243
|
gitStrict,
|
|
7244
|
+
VAULT_GENERATED_COMMIT_PATHS,
|
|
7186
7245
|
VAULT_COMMIT_PATHSPEC,
|
|
7187
7246
|
stageVaultContentChanges,
|
|
7188
7247
|
resolveWikiS3Remote,
|
|
@@ -7208,6 +7267,10 @@ export {
|
|
|
7208
7267
|
markJournalSuperseded,
|
|
7209
7268
|
supersedeStaleReviewRequiredJournals,
|
|
7210
7269
|
resolveConfiguredSnapshotWorktree,
|
|
7270
|
+
DEFAULT_MANAGED_WRITE_WAIT_MS,
|
|
7271
|
+
MANAGED_WRITE_POLL_INTERVAL_MS,
|
|
7272
|
+
resolveManagedWriteWaitMs,
|
|
7273
|
+
runManagedWritePeerGate,
|
|
7211
7274
|
runManagedWritePreflight,
|
|
7212
7275
|
runManagedWriteTransaction
|
|
7213
7276
|
};
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
snapshotterAliasForLocalHost,
|
|
36
36
|
toUndirectedWeighted,
|
|
37
37
|
writeDotenv
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-EHUFPORA.js";
|
|
39
39
|
import {
|
|
40
40
|
atomicWriteText,
|
|
41
41
|
prepareTypedPage
|
|
@@ -325,10 +325,14 @@ async function runLogAppend(input) {
|
|
|
325
325
|
}
|
|
326
326
|
if (outcome.result.ok && outcome.result.data.appended && input.recordLastOp !== false) {
|
|
327
327
|
try {
|
|
328
|
+
const files = ["log.md"];
|
|
329
|
+
if (eventPath) {
|
|
330
|
+
files.push(eventPath);
|
|
331
|
+
}
|
|
328
332
|
appendLastOp(input.vault, {
|
|
329
333
|
operation: "log-append",
|
|
330
334
|
summary: `appended log entry (${outcome.result.data.entries_before}->${outcome.result.data.entries_after})`,
|
|
331
|
-
files
|
|
335
|
+
files,
|
|
332
336
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
333
337
|
});
|
|
334
338
|
} catch (error) {
|
|
@@ -2673,6 +2677,30 @@ import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
|
|
|
2673
2677
|
import { join as join15 } from "path";
|
|
2674
2678
|
import { execSync as execSync5 } from "child_process";
|
|
2675
2679
|
import { platform as platform3 } from "os";
|
|
2680
|
+
function readPushResultState(stateFile) {
|
|
2681
|
+
if (!existsSync12(stateFile)) return { exists: false };
|
|
2682
|
+
try {
|
|
2683
|
+
const content = readFileSync7(stateFile, "utf8");
|
|
2684
|
+
let result;
|
|
2685
|
+
let reason;
|
|
2686
|
+
let timestamp;
|
|
2687
|
+
for (const line of content.split(/\r?\n/)) {
|
|
2688
|
+
const trimmed = line.trim();
|
|
2689
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
2690
|
+
const eq = trimmed.indexOf("=");
|
|
2691
|
+
if (eq <= 0) continue;
|
|
2692
|
+
const k = trimmed.slice(0, eq).trim();
|
|
2693
|
+
const v = trimmed.slice(eq + 1).trim();
|
|
2694
|
+
if (k === "result") result = v;
|
|
2695
|
+
else if (k === "reason") reason = v;
|
|
2696
|
+
else if (k === "timestamp") timestamp = v;
|
|
2697
|
+
}
|
|
2698
|
+
const malformed = result !== "ok" && result !== "refused";
|
|
2699
|
+
return { exists: true, result, reason, timestamp, malformed };
|
|
2700
|
+
} catch {
|
|
2701
|
+
return { exists: true, malformed: true };
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2676
2704
|
function readVaultSyncConfig(home) {
|
|
2677
2705
|
try {
|
|
2678
2706
|
const content = readFileSync7(join15(home, ".skillwiki", ".env"), "utf8");
|
|
@@ -2749,6 +2777,86 @@ function ageMinutes(nowMs, tsMs) {
|
|
|
2749
2777
|
if (tsMs == null) return null;
|
|
2750
2778
|
return Math.floor((nowMs - tsMs) / 6e4);
|
|
2751
2779
|
}
|
|
2780
|
+
function checkPushAgeFromTimestamp(ts) {
|
|
2781
|
+
const lastPush = new Date(ts).getTime();
|
|
2782
|
+
if (isNaN(lastPush)) {
|
|
2783
|
+
return check(
|
|
2784
|
+
"warn",
|
|
2785
|
+
"vault_sync_last_push_age",
|
|
2786
|
+
"Vault sync last push recency",
|
|
2787
|
+
`Unparseable push timestamp: ${ts}`
|
|
2788
|
+
);
|
|
2789
|
+
}
|
|
2790
|
+
const ageSec = (Date.now() - lastPush) / 1e3;
|
|
2791
|
+
if (ageSec <= 180) {
|
|
2792
|
+
return check(
|
|
2793
|
+
"pass",
|
|
2794
|
+
"vault_sync_last_push_age",
|
|
2795
|
+
"Vault sync last push recency",
|
|
2796
|
+
`Last push ${ageSec.toFixed(0)}s ago`
|
|
2797
|
+
);
|
|
2798
|
+
}
|
|
2799
|
+
return check(
|
|
2800
|
+
"warn",
|
|
2801
|
+
"vault_sync_last_push_age",
|
|
2802
|
+
"Vault sync last push recency",
|
|
2803
|
+
`Last push ${Math.round(ageSec)}s ago (>3 min)`
|
|
2804
|
+
);
|
|
2805
|
+
}
|
|
2806
|
+
function checkPushAgeFromLog(logDir, logFile) {
|
|
2807
|
+
try {
|
|
2808
|
+
const logContent = readFileSync7(logFile, "utf8");
|
|
2809
|
+
const lines = logContent.trim().split("\n").filter(Boolean);
|
|
2810
|
+
if (lines.length === 0) {
|
|
2811
|
+
return check(
|
|
2812
|
+
"warn",
|
|
2813
|
+
"vault_sync_last_push_age",
|
|
2814
|
+
"Vault sync last push recency",
|
|
2815
|
+
"Log file is empty"
|
|
2816
|
+
);
|
|
2817
|
+
}
|
|
2818
|
+
const journalRe = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z) (OK push|FAIL)/;
|
|
2819
|
+
let lastLine;
|
|
2820
|
+
let match = null;
|
|
2821
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2822
|
+
match = lines[i].match(journalRe);
|
|
2823
|
+
if (match) {
|
|
2824
|
+
lastLine = lines[i];
|
|
2825
|
+
break;
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
if (!lastLine || !match) {
|
|
2829
|
+
const tail = lines[lines.length - 1];
|
|
2830
|
+
return check(
|
|
2831
|
+
"warn",
|
|
2832
|
+
"vault_sync_last_push_age",
|
|
2833
|
+
"Vault sync last push recency",
|
|
2834
|
+
`Last log entry: ${tail.slice(0, 80)}`
|
|
2835
|
+
);
|
|
2836
|
+
}
|
|
2837
|
+
if (match[2] === "FAIL") {
|
|
2838
|
+
return check(
|
|
2839
|
+
"error",
|
|
2840
|
+
"vault_sync_last_push_age",
|
|
2841
|
+
"Vault sync last push recency",
|
|
2842
|
+
`Last push failed: ${lastLine}`
|
|
2843
|
+
);
|
|
2844
|
+
}
|
|
2845
|
+
return checkPushAgeFromTimestamp(match[1]);
|
|
2846
|
+
} catch {
|
|
2847
|
+
return existsSync12(logDir) ? check(
|
|
2848
|
+
"warn",
|
|
2849
|
+
"vault_sync_last_push_age",
|
|
2850
|
+
"Vault sync last push recency",
|
|
2851
|
+
`Log file not found at ${logFile}`
|
|
2852
|
+
) : check(
|
|
2853
|
+
"error",
|
|
2854
|
+
"vault_sync_last_push_age",
|
|
2855
|
+
"Vault sync last push recency",
|
|
2856
|
+
`Log directory not found at ${logDir}`
|
|
2857
|
+
);
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2752
2860
|
function snapshotterHealthChecks(scope, logDir, env) {
|
|
2753
2861
|
const fixture = loadSnapshotFixture(env);
|
|
2754
2862
|
const cadence = fixture ? fixture.cadence_minutes : parseInt(env.VS_SNAPSHOT_CADENCE_MINUTES ?? "30", 10) || 30;
|
|
@@ -2861,6 +2969,7 @@ function vaultSyncChecks(input) {
|
|
|
2861
2969
|
skip("vault_sync_jobs_enabled", "Vault sync jobs enabled"),
|
|
2862
2970
|
skip("vault_sync_snapshot_service_result", "Vault sync snapshot service result"),
|
|
2863
2971
|
skip("vault_sync_last_push_age", "Vault sync last push recency"),
|
|
2972
|
+
skip("vault_sync_last_push_result", "Vault sync last push result"),
|
|
2864
2973
|
skip("vault_sync_snapshot_consecutive_failures", "Vault sync snapshot consecutive failures"),
|
|
2865
2974
|
skip("vault_sync_last_fetch_status", "Vault sync last fetch status"),
|
|
2866
2975
|
skip("vault_sync_filter_present", "Vault sync filter file present"),
|
|
@@ -2869,6 +2978,7 @@ function vaultSyncChecks(input) {
|
|
|
2869
2978
|
}
|
|
2870
2979
|
const isMac = os === "darwin";
|
|
2871
2980
|
const logDir = input.logDir ?? (isMac ? join15(home, "Library", "Logs") : join15(home, ".local", "state", "vault-sync", "log"));
|
|
2981
|
+
const cacheDir = input.cacheDir ?? (isMac ? join15(home, "Library", "Caches", "vault-sync") : join15(home, ".cache", "vault-sync"));
|
|
2872
2982
|
const shareDir = input.shareDir ?? (isMac ? join15(home, "Library", "Application Support", "vault-sync", "bin") : join15(home, ".local", "share", "vault-sync", "bin"));
|
|
2873
2983
|
const filterPath = input.filterPath ?? join15(home, ".config", "rclone", "wiki-push-filters.txt");
|
|
2874
2984
|
const packagedSnapshotPath = join15(shareDir, "wiki-snapshot.sh");
|
|
@@ -2979,75 +3089,56 @@ function vaultSyncChecks(input) {
|
|
|
2979
3089
|
"Scheduler check failed \u2014 run vault-sync-install"
|
|
2980
3090
|
);
|
|
2981
3091
|
}
|
|
3092
|
+
const stateFile = join15(cacheDir, "wiki-push-result.state");
|
|
3093
|
+
const pushState = readPushResultState(stateFile);
|
|
2982
3094
|
const logFile = join15(logDir, "wiki-push.log");
|
|
2983
3095
|
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",
|
|
3096
|
+
if (pushState.exists && !pushState.malformed && pushState.result === "refused") {
|
|
3097
|
+
const reasonSuffix = pushState.reason ? `: ${pushState.reason}` : "";
|
|
3098
|
+
c3 = check(
|
|
3099
|
+
"error",
|
|
3043
3100
|
"vault_sync_last_push_age",
|
|
3044
3101
|
"Vault sync last push recency",
|
|
3045
|
-
`
|
|
3046
|
-
)
|
|
3047
|
-
|
|
3102
|
+
`Last push refused${reasonSuffix}`
|
|
3103
|
+
);
|
|
3104
|
+
} else if (pushState.exists && !pushState.malformed && pushState.result === "ok") {
|
|
3105
|
+
c3 = pushState.timestamp ? checkPushAgeFromTimestamp(pushState.timestamp) : check(
|
|
3106
|
+
"warn",
|
|
3048
3107
|
"vault_sync_last_push_age",
|
|
3049
3108
|
"Vault sync last push recency",
|
|
3050
|
-
|
|
3109
|
+
"State file missing timestamp"
|
|
3110
|
+
);
|
|
3111
|
+
} else {
|
|
3112
|
+
c3 = checkPushAgeFromLog(logDir, logFile);
|
|
3113
|
+
}
|
|
3114
|
+
let cPushResult;
|
|
3115
|
+
if (!pushState.exists) {
|
|
3116
|
+
cPushResult = check(
|
|
3117
|
+
"warn",
|
|
3118
|
+
"vault_sync_last_push_result",
|
|
3119
|
+
"Vault sync last push result",
|
|
3120
|
+
`no push result state file (push may not have run yet): ${stateFile}`
|
|
3121
|
+
);
|
|
3122
|
+
} else if (pushState.malformed) {
|
|
3123
|
+
cPushResult = check(
|
|
3124
|
+
"warn",
|
|
3125
|
+
"vault_sync_last_push_result",
|
|
3126
|
+
"Vault sync last push result",
|
|
3127
|
+
`malformed state file: ${stateFile}`
|
|
3128
|
+
);
|
|
3129
|
+
} else if (pushState.result === "ok") {
|
|
3130
|
+
cPushResult = check(
|
|
3131
|
+
"pass",
|
|
3132
|
+
"vault_sync_last_push_result",
|
|
3133
|
+
"Vault sync last push result",
|
|
3134
|
+
`result=ok timestamp=${pushState.timestamp ?? ""}`
|
|
3135
|
+
);
|
|
3136
|
+
} else {
|
|
3137
|
+
cPushResult = check(
|
|
3138
|
+
"error",
|
|
3139
|
+
"vault_sync_last_push_result",
|
|
3140
|
+
"Vault sync last push result",
|
|
3141
|
+
`result=refused reason=${pushState.reason ?? ""} timestamp=${pushState.timestamp ?? ""}`
|
|
3051
3142
|
);
|
|
3052
3143
|
}
|
|
3053
3144
|
const fetchLogFile = join15(logDir, "wiki-fetch.log");
|
|
@@ -3182,7 +3273,7 @@ function vaultSyncChecks(input) {
|
|
|
3182
3273
|
);
|
|
3183
3274
|
}
|
|
3184
3275
|
}
|
|
3185
|
-
return [c1, c2, c3, cFetch, c4, c5];
|
|
3276
|
+
return [c1, c2, c3, cPushResult, cFetch, c4, c5];
|
|
3186
3277
|
}
|
|
3187
3278
|
function checkVaultSyncPullHelper(home, env) {
|
|
3188
3279
|
const path = resolveVaultSyncPullHelper({
|
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-Q23OSECM.js";
|
|
54
54
|
import {
|
|
55
55
|
normalizeDistTag,
|
|
56
56
|
readCache,
|
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
FLEET_REL_PATH,
|
|
69
69
|
REDACTED_MALFORMED_REFERENCE,
|
|
70
70
|
VAULT_COMMIT_PATHSPEC,
|
|
71
|
+
VAULT_GENERATED_COMMIT_PATHS,
|
|
71
72
|
acquireOwnedSyncLock,
|
|
72
73
|
appendLastOp,
|
|
73
74
|
applyRawStructuralMove,
|
|
@@ -146,7 +147,7 @@ import {
|
|
|
146
147
|
supersedeStaleReviewRequiredJournals,
|
|
147
148
|
taxonomyCommentForPage,
|
|
148
149
|
writeDotenv
|
|
149
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-EHUFPORA.js";
|
|
150
151
|
import {
|
|
151
152
|
assertTargetInsideVault,
|
|
152
153
|
atomicWriteText,
|
|
@@ -3041,11 +3042,12 @@ function classifyLog(path, id, label, okPattern) {
|
|
|
3041
3042
|
if (!existsSync6(path)) return { id, label, status: "warn", detail: `log file missing: ${path}` };
|
|
3042
3043
|
const lines = readFileSync10(path, "utf8").split(/\r?\n/).filter(Boolean);
|
|
3043
3044
|
if (lines.length === 0) return { id, label, status: "warn", detail: `log file empty: ${path}` };
|
|
3045
|
+
const journalFailRe = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z (FAIL|ERROR)\b/;
|
|
3044
3046
|
const statusLine = [...lines].reverse().find(
|
|
3045
|
-
(line) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z /.test(line) && (okPattern.test(line) ||
|
|
3047
|
+
(line) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z /.test(line) && (okPattern.test(line) || journalFailRe.test(line))
|
|
3046
3048
|
);
|
|
3047
3049
|
const last = statusLine ?? lines[lines.length - 1];
|
|
3048
|
-
if (
|
|
3050
|
+
if (journalFailRe.test(last)) return { id, label, status: "error", detail: last.slice(0, 120) };
|
|
3049
3051
|
if (okPattern.test(last)) return { id, label, status: "pass", detail: last.slice(0, 120) };
|
|
3050
3052
|
return { id, label, status: "warn", detail: last.slice(0, 120) };
|
|
3051
3053
|
}
|
|
@@ -9900,7 +9902,21 @@ async function runFleetHealth(input) {
|
|
|
9900
9902
|
|
|
9901
9903
|
// src/utils/auto-commit.ts
|
|
9902
9904
|
import { existsSync as existsSync14 } from "fs";
|
|
9903
|
-
import { join as join41 } from "path";
|
|
9905
|
+
import { isAbsolute, join as join41, normalize } from "path";
|
|
9906
|
+
function isValidLastOpPath(file) {
|
|
9907
|
+
if (!file || typeof file !== "string") return false;
|
|
9908
|
+
const trimmed = file.trim();
|
|
9909
|
+
if (trimmed.length === 0) return false;
|
|
9910
|
+
if (isAbsolute(trimmed)) return false;
|
|
9911
|
+
const normalized = normalize(trimmed).replace(/\\/g, "/");
|
|
9912
|
+
if (normalized.startsWith("../") || normalized === ".." || normalized.includes("/../")) return false;
|
|
9913
|
+
for (const generatedPath of VAULT_GENERATED_COMMIT_PATHS) {
|
|
9914
|
+
if (normalized === generatedPath || normalized.startsWith(`${generatedPath}/`)) {
|
|
9915
|
+
return false;
|
|
9916
|
+
}
|
|
9917
|
+
}
|
|
9918
|
+
return true;
|
|
9919
|
+
}
|
|
9904
9920
|
async function postCommit(vault, exitCode) {
|
|
9905
9921
|
if (exitCode !== 0) return;
|
|
9906
9922
|
const home = process.env.HOME ?? "";
|
|
@@ -9912,16 +9928,31 @@ async function postCommit(vault, exitCode) {
|
|
|
9912
9928
|
if (lastOps.length === 0) return;
|
|
9913
9929
|
const porcelain = git(vault, ["status", "--porcelain", "--", ...VAULT_COMMIT_PATHSPEC]);
|
|
9914
9930
|
if (!porcelain || porcelain.trim().length === 0) return;
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9931
|
+
const rawFiles = lastOps.flatMap((op) => op.files ?? []);
|
|
9932
|
+
const candidateFiles = Array.from(new Set(rawFiles)).filter(isValidLastOpPath);
|
|
9933
|
+
if (candidateFiles.length === 0) {
|
|
9934
|
+
try {
|
|
9935
|
+
stageVaultContentChanges(vault);
|
|
9936
|
+
} catch (e) {
|
|
9937
|
+
process.stderr.write(`auto-commit: stage vault content failed: ${String(e)}
|
|
9919
9938
|
`);
|
|
9920
|
-
|
|
9939
|
+
return;
|
|
9940
|
+
}
|
|
9941
|
+
} else {
|
|
9942
|
+
try {
|
|
9943
|
+
gitStrict(vault, ["add", "--", ...candidateFiles]);
|
|
9944
|
+
} catch (e) {
|
|
9945
|
+
process.stderr.write(`auto-commit: git add failed: ${String(e)}
|
|
9946
|
+
`);
|
|
9947
|
+
return;
|
|
9948
|
+
}
|
|
9921
9949
|
}
|
|
9950
|
+
const staged = git(vault, ["diff", "--cached", "--name-only"]);
|
|
9951
|
+
if (!staged || staged.trim().length === 0) return;
|
|
9922
9952
|
const commitMessage = lastOps.map((op) => `${op.operation}: ${op.summary} (${op.files.length} files)`).join("; ");
|
|
9923
9953
|
try {
|
|
9924
|
-
|
|
9954
|
+
const commitArgs = candidateFiles.length === 0 ? ["commit", "-m", commitMessage] : ["commit", "-m", commitMessage, "--", ...candidateFiles];
|
|
9955
|
+
gitStrict(vault, commitArgs);
|
|
9925
9956
|
} catch (e) {
|
|
9926
9957
|
process.stderr.write(`auto-commit: git commit failed: ${String(e)}
|
|
9927
9958
|
`);
|
|
@@ -10068,7 +10099,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
|
|
|
10068
10099
|
if (dirty) {
|
|
10069
10100
|
return emit(dirty, void 0, { postCommit: false });
|
|
10070
10101
|
}
|
|
10071
|
-
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-
|
|
10102
|
+
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-CMVCRXRG.js");
|
|
10072
10103
|
const run = await runManagedWriteTransaction2({
|
|
10073
10104
|
vault,
|
|
10074
10105
|
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-EHUFPORA.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-Q23OSECM.js";
|
|
5
5
|
import "./chunk-7I2TPIV5.js";
|
|
6
6
|
import "./chunk-O3HCB7R2.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-EHUFPORA.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.54",
|
|
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-VRK5DOC5.js";
|
|
6
|
-
import "./chunk-74OSLCXE.js";
|
|
7
|
-
import "./chunk-GAHMWLWU.js";
|
|
8
|
-
import "./chunk-IJ7DD7QZ.js";
|
|
9
|
-
export {
|
|
10
|
-
runManagedWritePreflight,
|
|
11
|
-
runManagedWriteTransaction
|
|
12
|
-
};
|