skillwiki 0.8.1-beta.4 → 0.8.1-beta.6
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
|
@@ -4103,6 +4103,37 @@ function writeTest(dir) {
|
|
|
4103
4103
|
}
|
|
4104
4104
|
return { success: true, writeMs, readMs: Date.now() - readStart, size: Buffer.byteLength(payload, "utf8") };
|
|
4105
4105
|
}
|
|
4106
|
+
var DURATION_UNIT_SECONDS = {
|
|
4107
|
+
ms: 1 / 1e3,
|
|
4108
|
+
s: 1,
|
|
4109
|
+
m: 60,
|
|
4110
|
+
h: 3600,
|
|
4111
|
+
d: 86400,
|
|
4112
|
+
w: 604800
|
|
4113
|
+
};
|
|
4114
|
+
function parseDurationSeconds(raw) {
|
|
4115
|
+
const input = raw.trim().toLowerCase();
|
|
4116
|
+
if (!input) return null;
|
|
4117
|
+
if (/^\d+(?:\.\d+)?$/.test(input)) {
|
|
4118
|
+
const num = parseFloat(input);
|
|
4119
|
+
return Number.isFinite(num) ? num : null;
|
|
4120
|
+
}
|
|
4121
|
+
const re = /(\d+(?:\.\d+)?)(ms|s|m|h|d|w)/g;
|
|
4122
|
+
let total = 0;
|
|
4123
|
+
let consumed = 0;
|
|
4124
|
+
for (const match of input.matchAll(re)) {
|
|
4125
|
+
const full = match[0];
|
|
4126
|
+
const value = parseFloat(match[1]);
|
|
4127
|
+
const unit = match[2];
|
|
4128
|
+
if (!Number.isFinite(value)) return null;
|
|
4129
|
+
const factor = DURATION_UNIT_SECONDS[unit];
|
|
4130
|
+
if (factor === void 0) return null;
|
|
4131
|
+
total += value * factor;
|
|
4132
|
+
consumed += full.length;
|
|
4133
|
+
}
|
|
4134
|
+
if (consumed !== input.length) return null;
|
|
4135
|
+
return total;
|
|
4136
|
+
}
|
|
4106
4137
|
var FLAG_THRESHOLDS = {
|
|
4107
4138
|
"--vfs-write-back": { min: 15, unit: "s", label: "VFS write-back window" },
|
|
4108
4139
|
"--vfs-write-wait": { min: 10, unit: "s", label: "VFS write-wait" },
|
|
@@ -4495,6 +4526,73 @@ function checkS3MountPerf(resolvedPath) {
|
|
|
4495
4526
|
`S3 FUSE mount, cache warm (rg scan: ${elapsed.toFixed(3)}s)`
|
|
4496
4527
|
);
|
|
4497
4528
|
}
|
|
4529
|
+
var MAX_DIR_CACHE_TIME_SECONDS = 15 * 60;
|
|
4530
|
+
function formatDurationForHumans(seconds) {
|
|
4531
|
+
if (!Number.isFinite(seconds)) return `${seconds}s`;
|
|
4532
|
+
if (seconds >= 3600) return `${(seconds / 3600).toFixed(1)}h`;
|
|
4533
|
+
if (seconds >= 60) return `${(seconds / 60).toFixed(1)}m`;
|
|
4534
|
+
if (seconds >= 1) return `${seconds.toFixed(1)}s`;
|
|
4535
|
+
return `${Math.round(seconds * 1e3)}ms`;
|
|
4536
|
+
}
|
|
4537
|
+
function checkS3MountFreshness(resolvedPath) {
|
|
4538
|
+
if (!resolvedPath) {
|
|
4539
|
+
return check("pass", "s3_mount_freshness", "S3 visibility freshness", "No vault path \u2014 check skipped");
|
|
4540
|
+
}
|
|
4541
|
+
const fuse = detectFuseMount(resolvedPath);
|
|
4542
|
+
if (!fuse) {
|
|
4543
|
+
return check("pass", "s3_mount_freshness", "S3 visibility freshness", "local disk \u2014 check skipped");
|
|
4544
|
+
}
|
|
4545
|
+
const pid = findRcloneMountPid();
|
|
4546
|
+
if (pid === null) {
|
|
4547
|
+
return check(
|
|
4548
|
+
"warn",
|
|
4549
|
+
"s3_mount_freshness",
|
|
4550
|
+
"S3 visibility freshness",
|
|
4551
|
+
`S3 FUSE mount (${fuse.mountPoint}) but no rclone process found \u2014 cannot audit --dir-cache-time`
|
|
4552
|
+
);
|
|
4553
|
+
}
|
|
4554
|
+
const flags = parseRcloneFlags(pid);
|
|
4555
|
+
if (flags.size === 0) {
|
|
4556
|
+
return check(
|
|
4557
|
+
"warn",
|
|
4558
|
+
"s3_mount_freshness",
|
|
4559
|
+
"S3 visibility freshness",
|
|
4560
|
+
`rclone PID ${pid} found but could not parse flags`
|
|
4561
|
+
);
|
|
4562
|
+
}
|
|
4563
|
+
const raw = flags.get("--dir-cache-time");
|
|
4564
|
+
if (!raw) {
|
|
4565
|
+
return check(
|
|
4566
|
+
"pass",
|
|
4567
|
+
"s3_mount_freshness",
|
|
4568
|
+
"S3 visibility freshness",
|
|
4569
|
+
"PID " + pid + ": --dir-cache-time not set (rclone default 5m, within <=15m SLA)"
|
|
4570
|
+
);
|
|
4571
|
+
}
|
|
4572
|
+
const seconds = parseDurationSeconds(raw);
|
|
4573
|
+
if (seconds === null) {
|
|
4574
|
+
return check(
|
|
4575
|
+
"warn",
|
|
4576
|
+
"s3_mount_freshness",
|
|
4577
|
+
"S3 visibility freshness",
|
|
4578
|
+
`PID ${pid}: could not parse --dir-cache-time=${raw}`
|
|
4579
|
+
);
|
|
4580
|
+
}
|
|
4581
|
+
if (seconds > MAX_DIR_CACHE_TIME_SECONDS) {
|
|
4582
|
+
return check(
|
|
4583
|
+
"warn",
|
|
4584
|
+
"s3_mount_freshness",
|
|
4585
|
+
"S3 visibility freshness",
|
|
4586
|
+
`PID ${pid}: --dir-cache-time=${raw} (${formatDurationForHumans(seconds)}) exceeds 15m SLA \u2014 external S3 changes may remain invisible`
|
|
4587
|
+
);
|
|
4588
|
+
}
|
|
4589
|
+
return check(
|
|
4590
|
+
"pass",
|
|
4591
|
+
"s3_mount_freshness",
|
|
4592
|
+
"S3 visibility freshness",
|
|
4593
|
+
`PID ${pid}: --dir-cache-time=${raw} (${formatDurationForHumans(seconds)}), within <=15m SLA`
|
|
4594
|
+
);
|
|
4595
|
+
}
|
|
4498
4596
|
function checkRcloneFlagAudit(resolvedPath) {
|
|
4499
4597
|
if (!resolvedPath) {
|
|
4500
4598
|
return check("pass", "rclone_flags", "rclone VFS flags", "No vault path \u2014 check skipped");
|
|
@@ -4518,11 +4616,8 @@ function checkRcloneFlagAudit(resolvedPath) {
|
|
|
4518
4616
|
warnings.push(`${flag} not set (default may be unsafe)`);
|
|
4519
4617
|
continue;
|
|
4520
4618
|
}
|
|
4521
|
-
const
|
|
4522
|
-
if (
|
|
4523
|
-
let inSeconds = value;
|
|
4524
|
-
if (raw.endsWith("h")) inSeconds = value * 3600;
|
|
4525
|
-
else if (raw.endsWith("m")) inSeconds = value * 60;
|
|
4619
|
+
const inSeconds = parseDurationSeconds(raw);
|
|
4620
|
+
if (inSeconds === null) continue;
|
|
4526
4621
|
const thresholdSec = threshold.unit === "h" ? threshold.min * 3600 : threshold.unit === "m" ? threshold.min * 60 : threshold.min;
|
|
4527
4622
|
if (inSeconds < thresholdSec) {
|
|
4528
4623
|
warnings.push(`${flag}=${raw} (recommended \u2265${threshold.min}${threshold.unit})`);
|
|
@@ -5057,6 +5152,7 @@ async function runDoctor(input) {
|
|
|
5057
5152
|
checks.push(checkSyncLastPush(resolvedPath));
|
|
5058
5153
|
checks.push(checkDotStoreClean(resolvedPath));
|
|
5059
5154
|
checks.push(checkS3MountPerf(resolvedPath));
|
|
5155
|
+
checks.push(checkS3MountFreshness(resolvedPath));
|
|
5060
5156
|
checks.push(checkRcloneFlagAudit(resolvedPath));
|
|
5061
5157
|
checks.push(checkRcloneVersion(resolvedPath, vsConfig.installed));
|
|
5062
5158
|
checks.push(checkWriteTest(resolvedPath));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.8.1-beta.
|
|
3
|
+
"version": "0.8.1-beta.6",
|
|
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": {
|
|
@@ -21,7 +21,7 @@ escape_for_json() {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
skill_escaped=$(escape_for_json "$skill_content")
|
|
24
|
-
session_context="
|
|
24
|
+
session_context="### Skillwiki Activation\n\nSkillwiki is active for this workspace. Below are the capability guidelines for local reference:\n\n${skill_escaped}"
|
|
25
25
|
|
|
26
26
|
# Uses printf instead of heredoc to work around bash 5.3+ heredoc hang.
|
|
27
27
|
printf '{\n "hookSpecificOutput": {\n "hookEventName": "SessionStart",\n "additionalContext": "%s"\n }\n}\n' "$session_context"
|
package/skills/package.json
CHANGED
|
@@ -3,16 +3,15 @@ version: 0.2.2
|
|
|
3
3
|
name: using-skillwiki
|
|
4
4
|
description: Invoke at session start or when knowledge-base tasks arise — maps skillwiki skills, dev-loop alignment, and PRD/TDD routing with plan-mode gate checks
|
|
5
5
|
---
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
</SUBAGENT-STOP>
|
|
6
|
+
*Note: If executing as a background subagent, skip this skill section.*
|
|
7
|
+
|
|
9
8
|
# using-skillwiki
|
|
10
9
|
You have skillwiki — a project-aware Karpathy-style knowledge base for Claude Code.
|
|
11
10
|
|
|
12
11
|
## Last Hook Gate (SessionStart)
|
|
13
12
|
|
|
14
|
-
This skill is
|
|
15
|
-
|
|
13
|
+
This skill is activated by the plugin during `startup|clear|compact` lifecycle events.
|
|
14
|
+
Use this section as procedural planning guidelines:
|
|
16
15
|
|
|
17
16
|
1. If the task requires spec/plan work, route through PRD skills (not built-in plan mode).
|
|
18
17
|
2. If `prd_layer` is `superpowers` or `tdd`, ensure `EnterPlanMode` is gated (`wiki-gate-plan-mode on` or `status` if uncertain).
|