# Changelog All notable changes to claude-obsidian. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [SemVer](https://semver.org/). ## [1.9.2] - 2026-05-27 (prompt-cache hardening + path-handling robustness) Ports Anthropic prompt-caching best practices into the **one** place the plugin calls the Anthropic API directly: tier-1 contextual-prefix generation in `scripts/contextual-prefix.py`. Verified by full-repo sweep that `cache_control` and the Anthropic API surface exist nowhere else (incl. `claude-canvas/`). No change to retrieval output — API payload shape + observability only. ### Changed - **Cache only above the Haiku floor** (`scripts/contextual-prefix.py`). The page-body `cache_control` marker is now attached only when the body clears the Haiku 4.5 minimum cacheable size (`HAIKU_CACHE_MIN_CHARS = 16384`, ~4096 tokens × 4 chars/token). Below the floor the Anthropic API silently ignores the marker, so the prior unconditional marker was a no-op that misled the reader. Extracted as the pure, unit-tested `cache_control_for()`. - `.claude-plugin/plugin.json` + `marketplace.json` version 1.9.1 → 1.9.2. ### Added - **Cache telemetry** (`scripts/contextual-prefix.py`). The tier-1 path now logs `cache: wrote= read= tok` from the response `usage` fields — integers only, never page content, preserving the v1.7.1 data-egress posture. Implements the docs' "monitor cache hit rates" guidance and reveals whether the body cache is actually firing given the floor. - **Sequential-invariant note** at the chunk loop (`process_page`), documenting that cache reads depend on chunk 0's response landing before chunk 1 is sent (Anthropic prompt-caching concurrency rule). Guards against a future parallelization silently zeroing every cache read. - `tests/test_contextual_prefix.py` — hermetic coverage of the `cache_control_for()` floor decision (below / at / above floor, empty body, floor constant matches the documented Haiku minimum). Wired into `make test` (now 9 suites) + `make test-contextual`. ### Documented - Tier-1 "prompt-cached" claim now states the ~16 KB Haiku floor in the `contextual-prefix.py` module docstring and the ingest diagrams in `docs/compound-vault-guide.md` and `skills/wiki-retrieve/SKILL.md`, so docs match runtime behavior. ### Fixed - **Explicit missing or out-of-vault page paths now fail cleanly** (`scripts/contextual-prefix.py`). A single explicit path that does not exist exits 3 (was: silent exit 0, swallowed by the `is_file()` filter in `main()`); a path resolving outside the vault exits 2 with a message (was: a raw `ValueError` traceback from `relative_to()`). `--all` runs are unaffected. - Removed the dead `EXIT_NO_ADDRESS` (exit 5) constant and its docstring entry — it was defined and documented but never raised. Renamed the shadowed `prefix` progress-label variable in `process_page` to `progress`. ### Verification - `make test`: 9 hermetic suites green; the contextual suite now mocks the API payload to assert `cache_control` attaches only above the floor and the model reply is truncated to one line. No regressions. - Explicit-path exit codes confirmed by run: missing in-vault path → 3, out-of-vault path → 2, valid page → 0, `--all` unaffected. - `python3 scripts/contextual-prefix.py wiki/getting-started.md --peek`: tier selection unchanged (synthetic without `--allow-egress`). - Live tier-1 telemetry leg (sends page bodies off-machine) requires explicit `--allow-egress` and is left to operator verification per the repo's consent design. ## [1.9.1] - 2026-05-18 (v1.9.0 audit hardening) Patch release closing **6 of 6 remaining HIGH/MEDIUM** findings from the v1.9.0 pre-public-promotion audit ([`docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md`](docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md)) plus 3 LOW hardening items. Composite score moves from 91.6 to ~94 raw average. Public-promotion ship verdict remains GREEN. ### Fixed (defensive hardening) - **H4 — stale-lock reaper wiring** (`hooks/hooks.json`). New SessionStart command runs `bash scripts/wiki-lock.sh clear-stale --max-age 3600` at every session resume/startup. Locks orphaned by a crashed batch ingest get reaped automatically on the next session, not just on operator demand. - **S2 — opt-out gate for PostToolUse auto-commit** (`hooks/hooks.json`). Hook now exits early if `.vault-meta/auto-commit.disabled` exists. Default behavior unchanged for existing users; per-vault opt-out is one `touch` away. Useful for shared repos, CI runs, or any scenario where the operator wants to commit manually. - **Data M3 — symlink canonicalization** (`scripts/wiki-lock.sh:110-142`). `validate_path()` previously rejected literal `..` segments but did not canonicalize symlinks. A symlink inside `wiki/` resolving outside `VAULT_ROOT` could escape. Now resolves via `python3 os.path.realpath` and rejects any path whose canonical form is outside `commonpath(VAULT_ROOT, target)`. Cross-platform (GNU coreutils + macOS BSD); no realpath flag dependency. - **Data M4 — `.vault-meta/locks/.gitkeep`** + gitignore pattern change. `.vault-meta/locks/*` (not the dir itself) is now ignored; `.gitkeep` is whitelisted so the directory ships on fresh clone. Runtime behavior unchanged (`ensure_dirs()` always created it lazily); this just removes the first-acquire side-effect on directory presence. - **Data M1 — rerank.py warning routes to hook.log** (`scripts/rerank.py:158-176`). When the embed-cache lock is unavailable after 3 tries, the WARN line now also appends to `.vault-meta/hook.log` with a timestamp, so users see the event via `wiki lint` or by tailing the log. stderr-only was invisible to most callers. - **S4 — ollama-localhost assert** (`bin/setup-retrieve.sh:97-117`). If `OLLAMA_URL` env var points off-localhost, refuse to probe unless `--allow-remote-ollama` is passed. Mirrors the existing `scripts/tiling-check.py:351` gate. Closes a defense-in-depth gap where a malicious env var could redirect probes to an attacker-controlled endpoint. ### Documented - **H2 + S3 — multi-tenant threat model** (`SECURITY.md`). New "Threat model: single-tenant vault" section documents three intentional design choices (cross-process lock release, auto-commit hook scope, filesystem-permission trust boundary) and the mitigations for shared-host deployments. Closes the documentation gap the audit flagged: the design choices are correct for single-tenant, but operators in shared-host scenarios deserve to know what changes for them. ### Changed - `.claude-plugin/plugin.json` + `marketplace.json` version 1.9.0 → 1.9.1. ### Deferred to v1.9.2 (not in this release) - **Data M2 — embed-cache + chunk-orphan GC**: new `--gc` subcommand for `bm25-index.py` + `contextual-prefix.py` that prunes entries whose backing pages no longer exist. Requires hermetic tests covering edge cases; scoped for a dedicated release. - **W1 — wiki/meta/ release-session note relocation**: 12 files with incoming wikilinks need a coordinated graph update. Bundled with References M1+M2 (17 dead wikilink targets) for one-pass wiki cleanup. - **Security S1 — Excalidraw checksum pin**: requires upstream release hash verification + maintenance burden for future releases. Tracked separately. - **GROW note from v1.9.0 audit — 7th always-check cut in `agents/verifier.md`**: cross-file string consistency check (catches the class of bug where a single-file fix should have been a multi-file cascade, like the 548d294 + F1-F5 sequence). ### Verification - `make test`: 8 hermetic suites green (~1234 assertions). No regressions. - Live symlink-escape test on `wiki-lock.sh validate_path`: `ln -s /tmp/foo ./escape && bash scripts/wiki-lock.sh acquire escape/x.md` correctly rejects with "path resolves outside vault via symlink". - Both plugin manifests parse as JSON. - Pre-push verifier agent dispatch on staged diff: SHIP, 0 BLOCKER, 0 HIGH. ## [1.9.0] - 2026-05-18 (10-principle thinking framework) Minor release adding the **10-principle thinking framework** as a first-class layer of the plugin. The framework (OBSERVE-OBSERVE-LISTEN-THINK-CONNECT-CONNECT-FEEL-ACCEPT-CREATE-GROW) is integrated at three levels: as the new `/think` skill, as an appendix on every existing SKILL.md, and as the methodology spine for the v1.8.0 pre-push audit (which used it as its phase structure). Skill count: 14 → **15**. ### Added - **`skills/think/SKILL.md`** — new skill #15. Canonical source for the 10-principle thinking loop. Walks Claude through external observation, metacognition (the often-skipped one), active listening, first-principles analysis (six-cut kernel lives here), lateral connection, system orchestration, intuition, intellectual humility (anti-sycophancy enforcement), generative output, and iterative growth. Triggers on "think this through", "10-principle review", "/think", "OBSERVE LISTEN THINK", "deep think", "systematic thinking", "structured reasoning". Allowed tools: `Read, Grep, Glob, Bash` (read-only; loads structure and discipline, not mutation). ~250 lines covering the 10 principles with one-paragraph definitions, when-to-invoke guidance, stage-by-stage prompts (5 questions per stage), anti-patterns (the common skips), and composition notes with `/best-practices`, `/save`, `/wiki-lint`, `agents/verifier.md`, and `/autoresearch`. ### Changed - **All 14 existing SKILL.md files** — each receives a unique "## How to think (10-principle mapping)" appendix at the end. Per-skill 10-row table mapping each principle to that skill's specific work. Examples: wiki-mode's OBSERVE-internal is "audit the assumption that mode=generic is the default"; autoresearch's OBSERVE-internal is "am I steering the search toward what I already expect to find? confirmation bias kills research"; wiki-lint's FEEL is "a lint report should empower, not shame". Each appendix is non-trivial and skill-specific (not a template stub), satisfying the plan's verification rule #12. - **`.claude-plugin/plugin.json` + `marketplace.json`** — version 1.8.2 → 1.9.0. Description unchanged (the framework is additive to the v1.8.0 + v1.8.2 surface). ### Repo hygiene (first-public-release prep) - **`CONTRIBUTING.md`** (NEW) — workflow, six-cut self-review checklist, commit conventions, test requirements. - **`CODE_OF_CONDUCT.md`** (NEW) — adopts Contributor Covenant v2.1 by reference. - **`SECURITY.md`** (NEW) — private disclosure policy, response SLA, scope, credit policy. - **`.github/ISSUE_TEMPLATE/bug_report.md`** (NEW) — reproduction + environment + skill-affected fields. - **`.github/ISSUE_TEMPLATE/feature_request.md`** (NEW) — scope + compatibility + testing fields. - **`.github/pull_request_template.md`** (NEW) — six-cut self-review + test results + verifier verdict + CHANGELOG reminder. - **`.github/workflows/test.yml`** (NEW) — CI runs `make test` on push/PR + validates SKILL.md frontmatter + agents `tools:` declaration + plugin manifest JSON validity. - **Manifest + doc URL updates** — `plugin.json`, `marketplace.json`, and 18 other files updated to reference the canonical repository URL. ### Why this release Per the v1.8.0 pre-push audit's GROW notes (`docs/audits/v1.8.0-pre-push-audit-2026-05-18.md` §10), the 10-principle framework proved its value as the AUDIT's mental spine — OBSERVE-internal forced explicit bias documentation; GROW forced a feedback-loop section. Shipping it as a first-class skill (and as appendices on all existing skills) makes the discipline available to every future invocation, not just to one-off audits. This is the GROW step of the audit itself, embodied in code. ### Compass axis status after v1.9.0 | Axis | v1.8.0 | v1.9.0 | |---|---|---| | Compounding wiki primitive | #1 | #1 | | Multi-writer safety | #1 | #1 | | Retrieval architecture (free tier) | #1 | #1 | | License / openness | #1 | #1 | | Methodology support | #1 | #1 (deepened by framework integration) | | Derivative outputs | NO | NO (v2.0 scope) | | GUI / install ergonomics | NO | NO (v2.5+ scope) | 5 of 7 axes #1 (unchanged count, but methodology axis deepens — claude-obsidian is now the only Claude+Obsidian plugin shipping methodology modes AND a first-class thinking-loop framework AND per-skill thinking guidance). ### Migration notes - v1.8.x vaults: no action needed. All existing skills work identically; the "How to think" appendix is additive guidance, not behavioral change. - `/think` is invocable from any project that has this plugin installed; it does not require a vault. - The framework can be invoked explicitly (`/think `) or applied implicitly when an existing skill's appendix references it. ### Composition - `/think` + `/save` = the canonical compounding loop. Apply the 10 principles to a problem; when done, save the insights worth not re-deriving. - `/think` + `/best-practices` = engineering discipline at the THINK stage of the framework. The six-cut kernel IS the inside of stage 4. - `/think` + `agents/verifier.md` = an OBSERVE-internal substitute for solo work — fresh-context reviewer that catches biases the chair missed. ## [1.8.2] - 2026-05-18 (pre-push audit closure) Patch release closing **all 4 HIGH findings + 1 leaked BLOCKER-class hardening** from the v1.8.0 pre-push audit. Audit: [`docs/audits/v1.8.0-pre-push-audit-2026-05-18.md`](docs/audits/v1.8.0-pre-push-audit-2026-05-18.md). Per the audit's strict push gate (any BLOCKER halts), v1.8.2 takes the release from YELLOW (0 BLOCKER / 4 HIGH) to GREEN (0 BLOCKER / 0 HIGH). ### Fixed - **H1 — `scripts/detect-transport.sh`: implement `manual_override`.** The documented escape hatch for MCP-only users (`"manual_override": true` in `transport.json`) was documented at `wiki/references/transport-fallback.md` but never honored by the script. v1.8.2 parses the existing snapshot BEFORE auto-detection; when `manual_override: true`, the user's `preferred` and `fallback_chain` are preserved across normal cycles AND `--force` refreshes. Auto-detection still runs to refresh the `available.cli.*` informational fields. Field round-trips through the JSON schema (new `"manual_override": ` in every snapshot). Verified by smoke test: a pinned `"preferred": "mcp-obsidian"` survived a `--force` refresh. - **H2 — `agents/wiki-ingest.md`: add `Bash` to tools + add `## Mode awareness (v1.8+)` section.** The parallel batch-ingest sub-agent was missing `Bash` in its `tools:` frontmatter despite mandating `bash scripts/wiki-lock.sh acquire/release` in its body — this defeated the v1.7 multi-writer safety guarantee. Sub-agent was also missing v1.8 mode-routing awareness, so batch-ingest in LYT/PARA/Zettelkasten vaults filed to v1.7 generic paths. Both gaps closed. - **H3 — `skills/autoresearch/SKILL.md`: new `## Web egress hygiene (v1.8.2+)` section.** Four sub-policies: (1) URL validation (reject `file://`, `javascript:`, RFC1918), (2) content sanitization before write (strip `