$npx -y skills add AgriciDaniel/claude-obsidian --skill wiki-foldRollup of wiki log entries into meta-pages. Reads the last 2^k entries from wiki/log.md, writes a structurally-idempotent fold page to wiki/folds/ that links back to children. Extractive summarization (no invention). Dry-run by default, stdout-only; commit mode writes and accepts
| 1 | # wiki-fold: Extractive Log Rollup |
| 2 | |
| 3 | Implements a bounded subset of Mechanism 1 from [[DragonScale Memory]]: flat fold over raw `wiki/log.md` entries. Fold-of-folds (hierarchical level-stacking) is **out of scope for this skill**; see "Scope boundary" below. |
| 4 | |
| 5 | A fold is **additive**: child log entries and their referenced pages are never modified, moved, or deleted. A fold is **extractive**: every outcome and theme in the output must be traceable to a specific child log entry. No invented facts, no synthesis beyond what the child entries support. |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | ## Scope boundary (explicit) |
| 10 | |
| 11 | This skill does **not** implement: |
| 12 | - Fold-of-folds / hierarchical level stacking (DragonScale spec calls for it; deferred to a future skill). |
| 13 | - Automatic triggering (folds are always human-invoked in Phase 1). |
| 14 | - Semantic-tiling dedup (Mechanism 3; separate skill). |
| 15 | |
| 16 | It **does** implement: |
| 17 | - Flat fold over raw log.md entries at a chosen batch exponent `k`. |
| 18 | - Structural idempotency via a deterministic fold ID. |
| 19 | - Extractive summarization with count-checking. |
| 20 | |
| 21 | When referring to level in frontmatter, use `batch_exponent: k` (not `level: k`), because this skill does not produce hierarchical levels. |
| 22 | |
| 23 | --- |
| 24 | |
| 25 | ## Modes |
| 26 | |
| 27 | | Mode | Writes? | Invocation | |
| 28 | |---|---|---| |
| 29 | | **dry-run (default)** | **No Write tool calls.** Emit fold content via Bash `cat`/`heredoc` to stdout only. | `fold the log, dry-run k=3` | |
| 30 | | **commit** | Uses Write/Edit tools. Each Write fires the repo PostToolUse hook which auto-commits wiki changes. Accept this. Compose full content first, then sequence writes. | `fold the log, commit k=3` (only after a clean dry-run) | |
| 31 | |
| 32 | **Why stdout-only in dry-run**: the repo's `hooks/hooks.json` PostToolUse hook fires on any `Write|Edit` and runs `git add wiki/ .raw/`. Writing to `/tmp` does not stage /tmp, but it still triggers the hook, which will commit *any pending wiki changes* under a generic message. Dry-run must leave zero residue. Bash stdout does not fire the hook. |
| 33 | |
| 34 | --- |
| 35 | |
| 36 | ## Concurrency (v1.7+) |
| 37 | |
| 38 | The fold-page write in commit mode MUST be preceded by `wiki-lock acquire`: |
| 39 | |
| 40 | ```bash |
| 41 | FOLD_PATH="wiki/folds/${FOLD_ID}.md" |
| 42 | bash scripts/wiki-lock.sh acquire "$FOLD_PATH" || { |
| 43 | echo "FAIL: another writer holds $FOLD_PATH; aborting fold."; exit 75 |
| 44 | } |
| 45 | # … write the fold via Write/Edit (which fires the PostToolUse hook) … |
| 46 | bash scripts/wiki-lock.sh release "$FOLD_PATH" |
| 47 | ``` |
| 48 | |
| 49 | Fold pages are deterministically named (`fold-k{K}-from-{DATE}-to-{DATE}-n{COUNT}.md`), so two parallel folds with the same parameters target the same path. Without the lock, they could overwrite each other's outputs. The duplicate-detection check inside this skill (already documented below) handles the "fold already exists" case at the SKILL level; the lock handles the in-flight-write race at the OS level. |
| 50 | |
| 51 | Dry-run mode does not acquire a lock (no writes happen). |
| 52 | |
| 53 | See `skills/wiki-ingest/SKILL.md` §Concurrency for the full lock semantics. |
| 54 | |
| 55 | --- |
| 56 | |
| 57 | ## Deterministic fold ID |
| 58 | |
| 59 | Every fold has an ID derived from its inputs: |
| 60 | |
| 61 | ``` |
| 62 | fold-k{K}-from-{EARLIEST-DATE}-to-{LATEST-DATE}-n{COUNT} |
| 63 | ``` |
| 64 | |
| 65 | Example: `fold-k3-from-2026-04-10-to-2026-04-23-n8`. |
| 66 | |
| 67 | The filename in commit mode is `wiki/folds/{FOLD-ID}.md`. No date-of-creation in the filename. No timestamp in the title. |
| 68 | |
| 69 | **Duplicate detection (required)**: before emitting any output, check if `wiki/folds/{FOLD-ID}.md` already exists. If so, report "Fold already exists at wiki/folds/{FOLD-ID}.md. Use --force to overwrite, or pick a different range." and stop. This is the no-op idempotency guarantee; byte-identical content is NOT guaranteed (LLM prose varies) but the filename and scope are. |
| 70 | |
| 71 | --- |
| 72 | |
| 73 | ## Parameters |
| 74 | |
| 75 | - `k` (default 4): batch exponent. Batch size = `2^k`. Typical values: k=3 (8), k=4 (16), k=5 (32). |
| 76 | - `range` (optional): explicit entry range `entries 1-16`. Overrides k. |
| 77 | - `--force`: overwrite an existing fold with the same ID. Default no. |
| 78 | - `--commit`: write to wiki/. Without it, dry-run stdout-only. |
| 79 | |
| 80 | If fewer than `2^k` log entries exist, report the shortfall and stop. Do not silently fold a partial batch. |
| 81 | |
| 82 | --- |
| 83 | |
| 84 | ## Procedure |
| 85 | |
| 86 | ### 1. Parse log entries |
| 87 | |
| 88 | ``` |
| 89 | grep -n "^## \[" wiki/log.md | head -{2^k} |
| 90 | ``` |
| 91 | |
| 92 | Record for each entry: line number, date, operation, title, and the following bullet lines until the next `## [` or end-of-section. |
| 93 | |
| 94 | ### 2. Extract child page identifiers |
| 95 | |
| 96 | From each entry's bullet list, extract: |
| 97 | - `Location: wiki/path/to/page.md` (the primary page) |
| 98 | - `[[Wikilinks]]` inline |
| 99 | - `Pages created:` and `Pages updated:` lists |
| 100 | |
| 101 | Build a structured children list: |
| 102 | ```yaml |
| 103 | children: |
| 104 | - date: |