skillwiki 0.10.12 → 0.10.14
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-YYWGP7DN.js → chunk-2AOOMDZ7.js} +148 -73
- package/dist/{chunk-TYN2IHBY.js → chunk-OWPQJOFG.js} +19 -11
- package/dist/{chunk-3ZVZ2YEE.js → chunk-UJLSUJB6.js} +5 -2
- package/dist/cli.js +476 -52
- package/dist/{managed-write-preflight-7TWSEZJZ.js → managed-write-preflight-M2HL6DDY.js} +2 -2
- package/dist/skillwiki-mcp.js +2 -2
- package/dist/vault-sync/scripts/lib/git-operation-journal.sh +106 -13
- package/dist/vault-sync/scripts/lib/managed-write-lock.sh +10 -7
- package/dist/vault-sync/scripts/wiki-snapshot.sh +14 -0
- 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/skills/skills/using-skillwiki/SKILL.md +3 -2
- package/skills/using-skillwiki/SKILL.md +3 -2
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runManagedWritePreflight,
|
|
4
4
|
runManagedWriteTransaction
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-UJLSUJB6.js";
|
|
6
|
+
import "./chunk-OWPQJOFG.js";
|
|
7
7
|
import "./chunk-C5OLZRRM.js";
|
|
8
8
|
export {
|
|
9
9
|
runManagedWritePreflight,
|
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-2AOOMDZ7.js";
|
|
5
5
|
import "./chunk-7I2TPIV5.js";
|
|
6
6
|
import "./chunk-NMUYMNNB.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-OWPQJOFG.js";
|
|
8
8
|
import "./chunk-C5OLZRRM.js";
|
|
9
9
|
|
|
10
10
|
// src/mcp-entry.ts
|
|
@@ -38,24 +38,40 @@ vault_sync_op_set_field() {
|
|
|
38
38
|
vault_sync_op_set_fields() {
|
|
39
39
|
local repo="$1" op_id="$2"
|
|
40
40
|
shift 2
|
|
41
|
-
local file tmp
|
|
41
|
+
local file tmp updates source
|
|
42
42
|
file="$(vault_sync_op_journal_path "$repo" "$op_id")" || return 1
|
|
43
43
|
tmp="$(mktemp)" || return 1
|
|
44
|
-
|
|
45
|
-
cp "$file" "$tmp" || { rm -f "$tmp"; return 1; }
|
|
46
|
-
else
|
|
47
|
-
: >"$tmp"
|
|
48
|
-
fi
|
|
44
|
+
updates="$(mktemp)" || { rm -f "$tmp"; return 1; }
|
|
49
45
|
while [ "$#" -ge 2 ]; do
|
|
50
|
-
|
|
51
|
-
BEGIN{found=0}
|
|
52
|
-
$1==k {print k"="v; found=1; next}
|
|
53
|
-
{print}
|
|
54
|
-
END{if(!found) print k"="v}
|
|
55
|
-
' "$tmp" >"${tmp}.new" || { rm -f "$tmp" "${tmp}.new"; return 1; }
|
|
56
|
-
mv "${tmp}.new" "$tmp"
|
|
46
|
+
printf '%s=%s\n' "$1" "$2" >>"$updates" || { rm -f "$tmp" "$updates"; return 1; }
|
|
57
47
|
shift 2
|
|
58
48
|
done
|
|
49
|
+
source="$file"
|
|
50
|
+
[ -f "$source" ] || source=/dev/null
|
|
51
|
+
awk -F= '
|
|
52
|
+
FNR==NR {
|
|
53
|
+
key=$1
|
|
54
|
+
if (!(key in replacement)) order[++count]=key
|
|
55
|
+
replacement[key]=substr($0, index($0,"=")+1)
|
|
56
|
+
next
|
|
57
|
+
}
|
|
58
|
+
{
|
|
59
|
+
key=$1
|
|
60
|
+
if (key in replacement) {
|
|
61
|
+
print key"="replacement[key]
|
|
62
|
+
seen[key]=1
|
|
63
|
+
next
|
|
64
|
+
}
|
|
65
|
+
print
|
|
66
|
+
}
|
|
67
|
+
END {
|
|
68
|
+
for (i=1; i<=count; i++) {
|
|
69
|
+
key=order[i]
|
|
70
|
+
if (!(key in seen)) print key"="replacement[key]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
' "$updates" "$source" >"$tmp" || { rm -f "$tmp" "$updates"; return 1; }
|
|
74
|
+
rm -f "$updates"
|
|
59
75
|
mv "$tmp" "$file"
|
|
60
76
|
}
|
|
61
77
|
|
|
@@ -160,6 +176,83 @@ vault_sync_op_find_review_required() {
|
|
|
160
176
|
return 1
|
|
161
177
|
}
|
|
162
178
|
|
|
179
|
+
# Mark one obsolete review-required handoff complete while preserving its audit
|
|
180
|
+
# trail. Caller must establish that no live owner is mutating the journal.
|
|
181
|
+
vault_sync_op_mark_superseded_stale_review_required() {
|
|
182
|
+
local repo="$1" op_id="$2" by="${3:-vault-sync-managed-preflight}"
|
|
183
|
+
local reason="$4" prior_reason="$5" now
|
|
184
|
+
if [ -z "$prior_reason" ] && [ -n "$reason" ] && [ "$reason" != "superseded-stale-review-required" ]; then
|
|
185
|
+
prior_reason="$reason"
|
|
186
|
+
fi
|
|
187
|
+
now="$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date +%Y-%m-%dT%H:%M:%S)"
|
|
188
|
+
vault_sync_op_set_fields "$repo" "$op_id" \
|
|
189
|
+
"phase" "complete" \
|
|
190
|
+
"handoff" "1" \
|
|
191
|
+
"reason" "superseded-stale-review-required" \
|
|
192
|
+
"prior_reason" "$prior_reason" \
|
|
193
|
+
"superseded_at" "$now" \
|
|
194
|
+
"cleared_by" "$by" \
|
|
195
|
+
"cleared_reason" "operator-or-preflight $now"
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
# Auto-supersede review-required handoffs whose target is already an ancestor
|
|
199
|
+
# of HEAD. Unrelated dirty WIP is preserved; active sequencers and unmerged
|
|
200
|
+
# paths fail closed. Returns nonzero while any applicable handoff remains open.
|
|
201
|
+
vault_sync_op_supersede_stale_review_required() {
|
|
202
|
+
local repo="$1" by="${2:-vault-sync-managed-preflight}"
|
|
203
|
+
local current_git_dir git_dir unmerged jdir jf op_id phase handoff journal_git_dir target unresolved
|
|
204
|
+
local reason prior_reason key value
|
|
205
|
+
|
|
206
|
+
current_git_dir="$(git -C "$repo" rev-parse --absolute-git-dir 2>/dev/null)" || return 1
|
|
207
|
+
git_dir="$current_git_dir"
|
|
208
|
+
if [ -d "$git_dir/rebase-merge" ] || [ -d "$git_dir/rebase-apply" ] \
|
|
209
|
+
|| [ -f "$git_dir/MERGE_HEAD" ] || [ -f "$git_dir/CHERRY_PICK_HEAD" ] \
|
|
210
|
+
|| [ -f "$git_dir/REVERT_HEAD" ]; then
|
|
211
|
+
return 1
|
|
212
|
+
fi
|
|
213
|
+
unmerged="$(git -C "$repo" ls-files -u 2>/dev/null | head -1 || true)"
|
|
214
|
+
[ -z "$unmerged" ] || return 1
|
|
215
|
+
|
|
216
|
+
jdir="$(vault_sync_op_journal_dir "$repo")" || return 1
|
|
217
|
+
[ -d "$jdir" ] || return 0
|
|
218
|
+
unresolved=""
|
|
219
|
+
for jf in "$jdir"/*.env; do
|
|
220
|
+
[ -f "$jf" ] || continue
|
|
221
|
+
op_id="$(basename "$jf" .env)"
|
|
222
|
+
phase=""
|
|
223
|
+
handoff=""
|
|
224
|
+
journal_git_dir=""
|
|
225
|
+
target=""
|
|
226
|
+
reason=""
|
|
227
|
+
prior_reason=""
|
|
228
|
+
while IFS='=' read -r key value; do
|
|
229
|
+
case "$key" in
|
|
230
|
+
phase) phase="$value" ;;
|
|
231
|
+
handoff) handoff="$value" ;;
|
|
232
|
+
worktree_git_dir) journal_git_dir="$value" ;;
|
|
233
|
+
target_oid) target="$value" ;;
|
|
234
|
+
reason) reason="$value" ;;
|
|
235
|
+
prior_reason) prior_reason="$value" ;;
|
|
236
|
+
esac
|
|
237
|
+
done <"$jf"
|
|
238
|
+
[ "$phase" = "review-required" ] && [ "$handoff" = "1" ] || continue
|
|
239
|
+
if [ -n "$journal_git_dir" ] && [ "$journal_git_dir" != "$current_git_dir" ]; then
|
|
240
|
+
continue
|
|
241
|
+
fi
|
|
242
|
+
if [ -z "$target" ]; then
|
|
243
|
+
[ -n "$unresolved" ] || unresolved="$op_id"
|
|
244
|
+
continue
|
|
245
|
+
fi
|
|
246
|
+
if git -C "$repo" merge-base --is-ancestor "$target" HEAD 2>/dev/null; then
|
|
247
|
+
vault_sync_op_mark_superseded_stale_review_required \
|
|
248
|
+
"$repo" "$op_id" "$by" "$reason" "$prior_reason" || return 1
|
|
249
|
+
else
|
|
250
|
+
[ -n "$unresolved" ] || unresolved="$op_id"
|
|
251
|
+
fi
|
|
252
|
+
done
|
|
253
|
+
[ -z "$unresolved" ]
|
|
254
|
+
}
|
|
255
|
+
|
|
163
256
|
vault_sync_op_preflight_blocker() {
|
|
164
257
|
local repo="$1" unmerged op_id git_dir
|
|
165
258
|
unmerged="$(git -C "$repo" diff --name-only --diff-filter=U 2>/dev/null || true)"
|
|
@@ -62,7 +62,7 @@ vault_sync_managed_lock_safe_to_reclaim() {
|
|
|
62
62
|
|
|
63
63
|
# Never reclaim during an active/leftover sequencer.
|
|
64
64
|
if [ -d "$git_dir/rebase-merge" ] || [ -d "$git_dir/rebase-apply" ] \
|
|
65
|
-
|| [ -
|
|
65
|
+
|| [ -f "$git_dir/MERGE_HEAD" ] || [ -f "$git_dir/CHERRY_PICK_HEAD" ] \
|
|
66
66
|
|| [ -f "$git_dir/REVERT_HEAD" ]; then
|
|
67
67
|
return 1
|
|
68
68
|
fi
|
|
@@ -72,13 +72,16 @@ vault_sync_managed_lock_safe_to_reclaim() {
|
|
|
72
72
|
return 1
|
|
73
73
|
fi
|
|
74
74
|
|
|
75
|
-
# When journal helpers are loaded,
|
|
76
|
-
#
|
|
77
|
-
|
|
75
|
+
# When journal helpers are loaded, a dead owner may close handoffs whose
|
|
76
|
+
# target is already in HEAD, then continue reclaim in this same acquire.
|
|
77
|
+
# Live owners never reach this function; active sequencers/unmerged paths
|
|
78
|
+
# already failed closed above. Any unresolved handoff still blocks reclaim.
|
|
79
|
+
if command -v vault_sync_op_supersede_stale_review_required >/dev/null 2>&1; then
|
|
80
|
+
vault_sync_op_supersede_stale_review_required \
|
|
81
|
+
"$repo" "vault-sync-managed-lock-reclaim" 2>/dev/null || return 1
|
|
82
|
+
elif command -v vault_sync_op_find_review_required >/dev/null 2>&1; then
|
|
78
83
|
review_op="$(vault_sync_op_find_review_required "$repo" 2>/dev/null || true)"
|
|
79
|
-
|
|
80
|
-
return 1
|
|
81
|
-
fi
|
|
84
|
+
[ -z "$review_op" ] || return 1
|
|
82
85
|
fi
|
|
83
86
|
|
|
84
87
|
return 0
|
|
@@ -309,6 +309,18 @@ log() {
|
|
|
309
309
|
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
+
# Emit the canonical snapshot-completion terminal record (v0.10.14).
|
|
313
|
+
# One stable machine-parseable line written for both pushed and no-change
|
|
314
|
+
# success outcomes. Failure paths must never call this.
|
|
315
|
+
# SNAPSHOT_COMPLETE schema=v1 outcome=<pushed|no-change> result=success ts=<ISO> head=<oid> origin=<oid|unknown>
|
|
316
|
+
emit_snapshot_complete() {
|
|
317
|
+
local outcome="$1"
|
|
318
|
+
local head_oid origin_oid
|
|
319
|
+
head_oid="$(git -C "$SNAPSHOT_WORKTREE" rev-parse HEAD 2>/dev/null || echo unknown)"
|
|
320
|
+
origin_oid="$(git -C "$SNAPSHOT_WORKTREE" rev-parse --verify -q origin/main 2>/dev/null || echo unknown)"
|
|
321
|
+
log "SNAPSHOT_COMPLETE schema=v1 outcome=${outcome} result=success ts=$(date -u +%Y-%m-%dT%H:%M:%SZ) head=${head_oid} origin=${origin_oid}"
|
|
322
|
+
}
|
|
323
|
+
|
|
312
324
|
validate_tombstone_prune_cap() {
|
|
313
325
|
case "$MAX_TOMBSTONE_PRUNES" in
|
|
314
326
|
''|*[!0-9]*)
|
|
@@ -731,6 +743,7 @@ fi
|
|
|
731
743
|
# Check for changes
|
|
732
744
|
if [ -z "$(git status --porcelain)" ]; then
|
|
733
745
|
log "No changes to commit"
|
|
746
|
+
emit_snapshot_complete "no-change"
|
|
734
747
|
exit 0
|
|
735
748
|
fi
|
|
736
749
|
|
|
@@ -807,6 +820,7 @@ done
|
|
|
807
820
|
if [ "$PUSH_SUCCESS" = true ]; then
|
|
808
821
|
log "Push successful"
|
|
809
822
|
log "Status: complete"
|
|
823
|
+
emit_snapshot_complete "pushed"
|
|
810
824
|
exit 0
|
|
811
825
|
else
|
|
812
826
|
log "ERROR: Push failed after $PUSH_RETRIES attempts"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.14",
|
|
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": {
|
package/skills/package.json
CHANGED
|
@@ -86,8 +86,9 @@ After upgrading to skillwiki **≥0.10.1** (or when managed write fails):
|
|
|
86
86
|
|
|
87
87
|
1. Run `skillwiki doctor` — checks `vault_sync_pull_helper` and `vault_sync_review_required_journals`.
|
|
88
88
|
2. If pull helper is missing: install `skillwiki@0.10.1+` (helper must resolve from `dist/vault-sync/scripts/`) and/or redeploy vault-sync host install. Last-resort override: `SKILLWIKI_VAULT_SYNC_PULL_HELPER` pointing at `wiki-pull-with-auto-resolve.sh` under host vault-sync `bin/` (macOS Application Support or Linux `~/.local/share/vault-sync/bin`).
|
|
89
|
-
3. If preflight reports `review-required` on a **clean** worktree: `skillwiki sync journal list`, then `skillwiki sync journal clear-stale --dry-run`, then `clear-stale` without dry-run.
|
|
90
|
-
4.
|
|
89
|
+
3. If preflight reports `review-required` on a **clean** worktree: `skillwiki sync journal list`, then `skillwiki sync journal clear-stale --dry-run`, then `clear-stale` without dry-run. Managed preflight automatically supersedes a handoff when its `target_oid` is already an ancestor of `HEAD` and Git has no active sequencer or unmerged paths; unrelated dirty WIP is preserved. When the same incident also left a dead-owner managed-write lock, that preflight reclaims it with a recovery record in the same invocation. Live owners, active sequencers/unmerged paths, missing/non-ancestor targets, and remaining review-required journals still fail closed.
|
|
90
|
+
4. **Protected snapshotter stale-journal cleanup (v0.10.14+):** On a known protected snapshotter (sg01) where `sync journal clear-stale` is blocked by `PROTECTED_SNAPSHOTTER_WRITE_BLOCKED`, use the attended one-shot maintenance authority instead: `skillwiki snapshot-maintenance journal clear-stale <snapshot-worktree> --dry-run --reason "<operator reason>"` to produce a state-bound approval ID, then `skillwiki snapshot-maintenance journal clear-stale <snapshot-worktree> --approve <id> --reason "<same reason>"` on an attended TTY to execute. This requires the exact configured snapshot worktree, the production snapshot flock, and recomputes the plan under the flock; it is the only allowlisted mutation across the protected boundary. No generic force flag or env bypass exists.
|
|
91
|
+
5. After `skillwiki update` across 0.10.1, read the printed Migration 0.10.1 notes.
|
|
91
92
|
|
|
92
93
|
Also mirror these pointers in vault-presync / vault-sync-status skills when operating pull/push.
|
|
93
94
|
|
|
@@ -86,8 +86,9 @@ After upgrading to skillwiki **≥0.10.1** (or when managed write fails):
|
|
|
86
86
|
|
|
87
87
|
1. Run `skillwiki doctor` — checks `vault_sync_pull_helper` and `vault_sync_review_required_journals`.
|
|
88
88
|
2. If pull helper is missing: install `skillwiki@0.10.1+` (helper must resolve from `dist/vault-sync/scripts/`) and/or redeploy vault-sync host install. Last-resort override: `SKILLWIKI_VAULT_SYNC_PULL_HELPER` pointing at `wiki-pull-with-auto-resolve.sh` under host vault-sync `bin/` (macOS Application Support or Linux `~/.local/share/vault-sync/bin`).
|
|
89
|
-
3. If preflight reports `review-required` on a **clean** worktree: `skillwiki sync journal list`, then `skillwiki sync journal clear-stale --dry-run`, then `clear-stale` without dry-run.
|
|
90
|
-
4.
|
|
89
|
+
3. If preflight reports `review-required` on a **clean** worktree: `skillwiki sync journal list`, then `skillwiki sync journal clear-stale --dry-run`, then `clear-stale` without dry-run. Managed preflight automatically supersedes a handoff when its `target_oid` is already an ancestor of `HEAD` and Git has no active sequencer or unmerged paths; unrelated dirty WIP is preserved. When the same incident also left a dead-owner managed-write lock, that preflight reclaims it with a recovery record in the same invocation. Live owners, active sequencers/unmerged paths, missing/non-ancestor targets, and remaining review-required journals still fail closed.
|
|
90
|
+
4. **Protected snapshotter stale-journal cleanup (v0.10.14+):** On a known protected snapshotter (sg01) where `sync journal clear-stale` is blocked by `PROTECTED_SNAPSHOTTER_WRITE_BLOCKED`, use the attended one-shot maintenance authority instead: `skillwiki snapshot-maintenance journal clear-stale <snapshot-worktree> --dry-run --reason "<operator reason>"` to produce a state-bound approval ID, then `skillwiki snapshot-maintenance journal clear-stale <snapshot-worktree> --approve <id> --reason "<same reason>"` on an attended TTY to execute. This requires the exact configured snapshot worktree, the production snapshot flock, and recomputes the plan under the flock; it is the only allowlisted mutation across the protected boundary. No generic force flag or env bypass exists.
|
|
91
|
+
5. After `skillwiki update` across 0.10.1, read the printed Migration 0.10.1 notes.
|
|
91
92
|
|
|
92
93
|
Also mirror these pointers in vault-presync / vault-sync-status skills when operating pull/push.
|
|
93
94
|
|