skillwiki 0.10.19 → 0.10.21
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-QJPCCW4N.js → chunk-65Q5UGND.js} +38 -12
- package/dist/{chunk-IGCW3DR2.js → chunk-I5JD3BQZ.js} +6 -0
- package/dist/{chunk-IAPD6YTC.js → chunk-UNPZDCWN.js} +18 -2
- package/dist/cli.js +6 -6
- package/dist/{index-projection-DENEYZTK.js → index-projection-HAXDEM2F.js} +1 -1
- package/dist/{managed-write-preflight-LO4LZ6OQ.js → managed-write-preflight-CTXX2MHQ.js} +1 -1
- package/dist/skillwiki-mcp.js +2 -2
- package/dist/vault-sync/scripts/lib/managed-write-lock.sh +4 -3
- 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
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
|
|
19
19
|
// src/utils/managed-write-preflight.ts
|
|
20
20
|
import { existsSync as existsSync2 } from "fs";
|
|
21
|
-
import { join as join2, resolve } from "path";
|
|
21
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
22
22
|
|
|
23
23
|
// src/utils/managed-write-lock.ts
|
|
24
24
|
import { randomBytes } from "crypto";
|
|
@@ -29,7 +29,8 @@ import {
|
|
|
29
29
|
unlinkSync,
|
|
30
30
|
writeFileSync
|
|
31
31
|
} from "fs";
|
|
32
|
-
import {
|
|
32
|
+
import { hostname } from "os";
|
|
33
|
+
import { dirname, join, resolve } from "path";
|
|
33
34
|
function managedWriteLockPath(vault) {
|
|
34
35
|
const gitPath = git(vault, ["rev-parse", "--git-path", "vault-sync/managed-write.lock"]);
|
|
35
36
|
if (gitPath) return gitPath.startsWith("/") ? gitPath : join(vault, gitPath);
|
|
@@ -65,19 +66,35 @@ function hasUnsafeGitState(vault) {
|
|
|
65
66
|
const unmerged = git(vault, ["ls-files", "-u"]);
|
|
66
67
|
return Boolean(unmerged && unmerged.trim().length > 0);
|
|
67
68
|
}
|
|
68
|
-
function
|
|
69
|
+
function isGitBackedVault(vault) {
|
|
70
|
+
return Boolean(git(vault, ["rev-parse", "--absolute-git-dir"]));
|
|
71
|
+
}
|
|
72
|
+
function hasLocalOwnerProof(vault, record) {
|
|
73
|
+
return isGitBackedVault(vault) || typeof record.owner_hostname === "string" && record.owner_hostname === hostname();
|
|
74
|
+
}
|
|
75
|
+
function reclaimDeadManagedWriteLockOwner(vault, options = {}) {
|
|
69
76
|
const path = managedWriteLockPath(vault);
|
|
77
|
+
const gitStateVault = resolve(options.gitStateVault ?? vault);
|
|
70
78
|
if (!existsSync(path)) return ok({ reclaimed: false });
|
|
71
79
|
const record = readLockRecord(path);
|
|
72
80
|
if (!record) {
|
|
73
81
|
return err("SYNC_LOCK_HELD", { path, message: "managed-write lock unreadable" });
|
|
74
82
|
}
|
|
83
|
+
if (!hasLocalOwnerProof(vault, record)) {
|
|
84
|
+
return err("SYNC_LOCK_HELD", {
|
|
85
|
+
path,
|
|
86
|
+
owner_hostname: record.owner_hostname,
|
|
87
|
+
current_hostname: hostname(),
|
|
88
|
+
message: "managed-write lock origin is foreign or unknown"
|
|
89
|
+
});
|
|
90
|
+
}
|
|
75
91
|
if (isManagedWriteLockOwnerAlive(record.pid)) {
|
|
76
92
|
return err("SYNC_LOCK_HELD", { path, message: "managed-write lock owner is alive" });
|
|
77
93
|
}
|
|
78
|
-
if (hasUnsafeGitState(
|
|
94
|
+
if (hasUnsafeGitState(gitStateVault)) {
|
|
79
95
|
return err("SYNC_LOCK_HELD", {
|
|
80
96
|
path,
|
|
97
|
+
git_state_vault: gitStateVault,
|
|
81
98
|
message: "managed-write lock not reclaimed: unsafe git state"
|
|
82
99
|
});
|
|
83
100
|
}
|
|
@@ -90,6 +107,7 @@ function reclaimDeadManagedWriteLockOwner(vault) {
|
|
|
90
107
|
recovered_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
91
108
|
recovery_reason: "owner_pid_dead",
|
|
92
109
|
owner_pid_alive: false,
|
|
110
|
+
git_state_vault: gitStateVault,
|
|
93
111
|
lock: record
|
|
94
112
|
};
|
|
95
113
|
writeFileSync(recoveryPath, `${JSON.stringify(meta, null, 2)}
|
|
@@ -107,7 +125,13 @@ function tryCreateLock(path, command) {
|
|
|
107
125
|
mkdirSync(dirname(path), { recursive: true });
|
|
108
126
|
writeFileSync(
|
|
109
127
|
path,
|
|
110
|
-
`${JSON.stringify({
|
|
128
|
+
`${JSON.stringify({
|
|
129
|
+
pid: process.pid,
|
|
130
|
+
owner_hostname: hostname(),
|
|
131
|
+
owner_token: ownerToken,
|
|
132
|
+
acquired,
|
|
133
|
+
command
|
|
134
|
+
})}
|
|
111
135
|
`,
|
|
112
136
|
{ flag: "wx" }
|
|
113
137
|
);
|
|
@@ -117,14 +141,14 @@ function tryCreateLock(path, command) {
|
|
|
117
141
|
return err("WRITE_FAILED", { path, message: String(error) });
|
|
118
142
|
}
|
|
119
143
|
}
|
|
120
|
-
function acquireManagedWriteLock(vault, command) {
|
|
144
|
+
function acquireManagedWriteLock(vault, command, options = {}) {
|
|
121
145
|
const path = managedWriteLockPath(vault);
|
|
122
146
|
const first = tryCreateLock(path, command);
|
|
123
147
|
if (first.ok) {
|
|
124
148
|
return ok({ ...first.data, vault });
|
|
125
149
|
}
|
|
126
150
|
if (first.error !== "SYNC_LOCK_HELD") return first;
|
|
127
|
-
const reclaimed = reclaimDeadManagedWriteLockOwner(vault);
|
|
151
|
+
const reclaimed = reclaimDeadManagedWriteLockOwner(vault, options);
|
|
128
152
|
if (!reclaimed.ok || !reclaimed.data.reclaimed) {
|
|
129
153
|
return err("SYNC_LOCK_HELD", { path });
|
|
130
154
|
}
|
|
@@ -180,8 +204,8 @@ function isGitVault(vault) {
|
|
|
180
204
|
return Boolean(git(vault, ["rev-parse", "--absolute-git-dir"]));
|
|
181
205
|
}
|
|
182
206
|
async function runManagedWritePreflight(input, deps = DEFAULT_DEPS) {
|
|
183
|
-
const mutationVault =
|
|
184
|
-
let convergenceVault = input.convergenceVault &&
|
|
207
|
+
const mutationVault = resolve2(input.vault);
|
|
208
|
+
let convergenceVault = input.convergenceVault && resolve2(input.convergenceVault) !== mutationVault ? resolve2(input.convergenceVault) : void 0;
|
|
185
209
|
let convergenceSource = convergenceVault ? "explicit" : "single-path";
|
|
186
210
|
const mutationBlocker = preflightBlocker(mutationVault);
|
|
187
211
|
if (mutationBlocker) {
|
|
@@ -264,7 +288,7 @@ async function runManagedWritePreflight(input, deps = DEFAULT_DEPS) {
|
|
|
264
288
|
})
|
|
265
289
|
};
|
|
266
290
|
}
|
|
267
|
-
convergenceVault =
|
|
291
|
+
convergenceVault = resolve2(configured);
|
|
268
292
|
convergenceSource = "configured";
|
|
269
293
|
if (convergenceVault === mutationVault) {
|
|
270
294
|
return {
|
|
@@ -373,8 +397,10 @@ async function runManagedWritePreflight(input, deps = DEFAULT_DEPS) {
|
|
|
373
397
|
};
|
|
374
398
|
}
|
|
375
399
|
async function runManagedWriteTransaction(input, deps = DEFAULT_DEPS) {
|
|
376
|
-
const mutationVault =
|
|
377
|
-
const lock = acquireManagedWriteLock(mutationVault, input.command
|
|
400
|
+
const mutationVault = resolve2(input.vault);
|
|
401
|
+
const lock = acquireManagedWriteLock(mutationVault, input.command, {
|
|
402
|
+
gitStateVault: input.convergenceVault ? resolve2(input.convergenceVault) : mutationVault
|
|
403
|
+
});
|
|
378
404
|
if (!lock.ok) {
|
|
379
405
|
return { exitCode: ExitCode.SYNC_LOCK_HELD, result: lock };
|
|
380
406
|
}
|
|
@@ -164,6 +164,11 @@ function redactMarker(kind, value) {
|
|
|
164
164
|
function isSyntheticPlaceholder(value) {
|
|
165
165
|
return REDACTED_RE.test(value) || SYNTHETIC_RE.test(value.trim());
|
|
166
166
|
}
|
|
167
|
+
function isNonSecretTokenCapture(value) {
|
|
168
|
+
if (value.startsWith("//")) return true;
|
|
169
|
+
if (/^[a-z]{2,}(?:-[a-z]{2,})+$/.test(value)) return true;
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
167
172
|
function collectMatches(text) {
|
|
168
173
|
const matches = [];
|
|
169
174
|
for (const matcher of MATCHERS) {
|
|
@@ -174,6 +179,7 @@ function collectMatches(text) {
|
|
|
174
179
|
if (REDACTED_RE.test(whole)) continue;
|
|
175
180
|
const value = matcher.valueGroup ? m[matcher.valueGroup] : whole;
|
|
176
181
|
if (isSyntheticPlaceholder(value)) continue;
|
|
182
|
+
if (matcher.kind === "token" && isNonSecretTokenCapture(value)) continue;
|
|
177
183
|
const valueOffset = whole.lastIndexOf(value);
|
|
178
184
|
const valueStart = start + Math.max(0, valueOffset);
|
|
179
185
|
matches.push({
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
splitFrontmatter,
|
|
20
20
|
vaultIoConcurrency,
|
|
21
21
|
writeRootIndexProjection
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-I5JD3BQZ.js";
|
|
23
23
|
import {
|
|
24
24
|
CONFIG_KEYS,
|
|
25
25
|
git,
|
|
@@ -3196,6 +3196,9 @@ function buildCliSurface() {
|
|
|
3196
3196
|
program.command("log-append").requiredOption("--content <text>").option("--operation-id <id>").option("--write-event").option("--wiki <name>");
|
|
3197
3197
|
program.command("work-complete").requiredOption("--work-item <path>").option("--operation-id <id>").option("--no-commit").option("--wiki <name>");
|
|
3198
3198
|
program.command("work-validate").requiredOption("--work-item <path>").option("--require-complete").option("--wiki <name>");
|
|
3199
|
+
program.command("log");
|
|
3200
|
+
program.command("index");
|
|
3201
|
+
program.command("projections");
|
|
3199
3202
|
program.command("lint").option("--days <n>").option("--lines <n>").option("--log-threshold <n>").option("--fix").option("--only <bucket>").option("--summary").option("--examples <n>").option("--wiki <name>");
|
|
3200
3203
|
program.command("config");
|
|
3201
3204
|
program.command("health").option("--wiki <name>").option("--sync <mode>").option("--no-fail").option("--out <path>").option("--examples <n>");
|
|
@@ -3225,6 +3228,7 @@ function buildCliSurface() {
|
|
|
3225
3228
|
program.command("fleet");
|
|
3226
3229
|
program.command("page");
|
|
3227
3230
|
program.command("write-preflight").option("--command <name>").option("--dirty-threshold <n>").option("--skip-dirty").option("--prior-artifact-file <path>").option("--prior-artifact-text <text>").option("--consecutive-no-decision <n>").option("--no-decision-threshold <n>").option("--human-allow").option("--mission-kind <kind>").option("--skip-mission").option("--project <slug>").option("--capture-day <date>").option("--capture-budget <n>").option("--severity <level>").option("--skip-budget").option("--checks <list>").option("--wiki <name>");
|
|
3231
|
+
program.command("mcp");
|
|
3228
3232
|
const graphCmd = program.commands.find((c) => c.name() === "graph");
|
|
3229
3233
|
graphCmd.command("build").option("--out <path>").option("--wiki <name>");
|
|
3230
3234
|
const canvasCmd = program.commands.find((c) => c.name() === "canvas");
|
|
@@ -3242,6 +3246,14 @@ function buildCliSurface() {
|
|
|
3242
3246
|
tagCmd.command("reconcile").requiredOption("--page <path>").option("--from <path>").option("--tags <csv>").option("--reason <text>").option("--write").option("--wiki <name>");
|
|
3243
3247
|
const pageCmd = program.commands.find((c) => c.name() === "page");
|
|
3244
3248
|
pageCmd.command("publish").requiredOption("--target <path>").option("--log-note <text>").option("--write").option("--wiki <name>");
|
|
3249
|
+
const logCmd = program.commands.find((c) => c.name() === "log");
|
|
3250
|
+
logCmd.command("materialize").option("--write").option("--wiki <name>");
|
|
3251
|
+
logCmd.command("migrate-legacy").option("--write").option("--converge-vault <dir>").option("--wiki <name>");
|
|
3252
|
+
const indexCmd = program.commands.find((c) => c.name() === "index");
|
|
3253
|
+
indexCmd.command("rebuild").option("--write").option("--wiki <name>");
|
|
3254
|
+
const projectionsCmd = program.commands.find((c) => c.name() === "projections");
|
|
3255
|
+
projectionsCmd.command("materialize").option("--write").option("--converge-vault <dir>").option("--wiki <name>");
|
|
3256
|
+
projectionsCmd.command("repair-legacy").requiredOption("--event-operation-id <id>").option("--write").option("--converge-vault <dir>").option("--wiki <name>");
|
|
3245
3257
|
const syncCmd = program.commands.find((c) => c.name() === "sync");
|
|
3246
3258
|
syncCmd.command("status").option("--wiki <name>").option("--include-stashes").option("--include-remote-health").option("--check-snapshotter");
|
|
3247
3259
|
syncCmd.command("push").option("--wiki <name>");
|
|
@@ -3346,7 +3358,8 @@ function validateCliRefs(text, page, surface) {
|
|
|
3346
3358
|
// src/utils/source-identity.ts
|
|
3347
3359
|
var PROJECT_PATTERNS = {
|
|
3348
3360
|
hermes: [/\bhermes\b/i, /nousresearch\s*hermes/i, /nousresearch\/hermes-agent/i, /hermes agent/i],
|
|
3349
|
-
|
|
3361
|
+
// normalize() splits CamelCase ("SkillWiki" → "skill wiki"), so match both forms.
|
|
3362
|
+
skillwiki: [/\bskillwiki\b/i, /\bskill\s+wiki\b/i, /\bllm[-_ ]?wiki\b/i, /karpathy'?s llm wiki/i],
|
|
3350
3363
|
superpowers: [/\bsuperpowers\b/i, /obra\/superpowers/i, /complete software development methodology/i],
|
|
3351
3364
|
playwright: [/\bplaywright\b/i, /microsoft\s*playwright/i, /microsoft\/playwright/i],
|
|
3352
3365
|
convex: [/\bconvex\b/i],
|
|
@@ -3359,6 +3372,9 @@ var PROJECT_PATTERNS = {
|
|
|
3359
3372
|
var COMPATIBLE = /* @__PURE__ */ new Set([
|
|
3360
3373
|
"hermes|skillwiki",
|
|
3361
3374
|
"skillwiki|hermes",
|
|
3375
|
+
// SkillWiki work items commonly reference Superpowers skills/methodology.
|
|
3376
|
+
"skillwiki|superpowers",
|
|
3377
|
+
"superpowers|skillwiki",
|
|
3362
3378
|
"proxmox|seaweedfs",
|
|
3363
3379
|
"seaweedfs|proxmox",
|
|
3364
3380
|
"coolify|seaweedfs",
|
package/dist/cli.js
CHANGED
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
upsertIndexEntry,
|
|
84
84
|
validateLogEvent,
|
|
85
85
|
writeLogEvent
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-UNPZDCWN.js";
|
|
87
87
|
import {
|
|
88
88
|
normalizeDistTag,
|
|
89
89
|
readCache,
|
|
@@ -105,11 +105,11 @@ import {
|
|
|
105
105
|
scanVault,
|
|
106
106
|
splitFrontmatter,
|
|
107
107
|
writeRootIndexProjection
|
|
108
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-I5JD3BQZ.js";
|
|
109
109
|
import {
|
|
110
110
|
runManagedWritePreflight,
|
|
111
111
|
runManagedWriteTransaction
|
|
112
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-65Q5UGND.js";
|
|
113
113
|
import {
|
|
114
114
|
FLEET_REL_PATH,
|
|
115
115
|
canSupersedeJournal,
|
|
@@ -3204,7 +3204,7 @@ ${fmRewritten}
|
|
|
3204
3204
|
await rename2(join18(input.vault, relPath), join18(input.vault, archivePath));
|
|
3205
3205
|
let indexUpdated = false;
|
|
3206
3206
|
if (!isRaw) {
|
|
3207
|
-
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-
|
|
3207
|
+
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-HAXDEM2F.js");
|
|
3208
3208
|
const before = await readFile7(join18(input.vault, "index.md"), "utf8").catch(() => "");
|
|
3209
3209
|
const fullTarget = relPath.replace(/\.md$/, "");
|
|
3210
3210
|
const bare = fullTarget.split("/").pop() ?? fullTarget;
|
|
@@ -3315,7 +3315,7 @@ async function runRemove(input) {
|
|
|
3315
3315
|
if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
|
|
3316
3316
|
const { readFile: readFile17 } = await import("fs/promises");
|
|
3317
3317
|
const { join: pathJoin } = await import("path");
|
|
3318
|
-
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-
|
|
3318
|
+
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-HAXDEM2F.js");
|
|
3319
3319
|
const before = await readFile17(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
|
|
3320
3320
|
const fullTarget = relPath.replace(/\.md$/, "");
|
|
3321
3321
|
const bare = fullTarget.split("/").pop() ?? fullTarget;
|
|
@@ -7862,7 +7862,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
|
|
|
7862
7862
|
if (dirty) {
|
|
7863
7863
|
return emit(dirty, void 0, { postCommit: false });
|
|
7864
7864
|
}
|
|
7865
|
-
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-
|
|
7865
|
+
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-CTXX2MHQ.js");
|
|
7866
7866
|
const run = await runManagedWriteTransaction2({
|
|
7867
7867
|
vault,
|
|
7868
7868
|
command,
|
package/dist/skillwiki-mcp.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runSkillwikiMcpStdio
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UNPZDCWN.js";
|
|
5
5
|
import "./chunk-7I2TPIV5.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-I5JD3BQZ.js";
|
|
7
7
|
import "./chunk-GNS2ZV5P.js";
|
|
8
8
|
import "./chunk-Y6KRDGI2.js";
|
|
9
9
|
|
|
@@ -159,7 +159,7 @@ vault_sync_managed_lock_reclaim_dead_owner() {
|
|
|
159
159
|
vault_sync_managed_lock_acquire() {
|
|
160
160
|
local repo="${1:-.}"
|
|
161
161
|
local command="${2:-wiki-pull}"
|
|
162
|
-
local path token now inherited attempt
|
|
162
|
+
local path token now owner_hostname inherited attempt
|
|
163
163
|
|
|
164
164
|
path="$(vault_sync_managed_lock_path "$repo")" || return 1
|
|
165
165
|
VAULT_SYNC_MANAGED_LOCK_PATH="$path"
|
|
@@ -185,8 +185,9 @@ vault_sync_managed_lock_acquire() {
|
|
|
185
185
|
token="$(od -An -N16 -tx1 /dev/urandom 2>/dev/null | tr -d ' \n')"
|
|
186
186
|
[ -n "$token" ] || token="$$-$(date +%s)"
|
|
187
187
|
now="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
owner_hostname="$(hostname 2>/dev/null || printf unknown)"
|
|
189
|
+
if ( set -o noclobber; printf '{"pid":%s,"owner_hostname":"%s","owner_token":"%s","acquired":"%s","command":"%s"}\n' \
|
|
190
|
+
"$$" "$owner_hostname" "$token" "$now" "$command" >"$path" ) 2>/dev/null; then
|
|
190
191
|
VAULT_SYNC_MANAGED_LOCK_TOKEN_OWNED="$token"
|
|
191
192
|
VAULT_SYNC_MANAGED_LOCK_ACQUIRED="$now"
|
|
192
193
|
VAULT_SYNC_MANAGED_LOCK_OWNS_RELEASE=1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.21",
|
|
4
4
|
"skills": "./",
|
|
5
5
|
"description": "Project-aware Karpathy-style knowledge base for Claude Code: 19 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI.",
|
|
6
6
|
"author": {
|