feat: capture-to-Obsidian bridge with eval-backed local enrichment#3
Merged
Conversation
Turn any translated selection into a Markdown note in an Obsidian vault via an obsidian://new URI opened from the content script — no new extension permissions, with a clipboard fallback for notes too large for a protocol URL. Every note carries a machine-readable YAML frontmatter written `status: raw` as a handoff contract to a downstream "second brain"; heavy synthesis is deliberately deferred rather than reimplemented on-device. Optional local-model enrichment (title/summary/tags) is off by default and strictly best-effort: parseEnrichResponse salvages usable metadata from fenced, preamble-wrapped, and trailing-prose replies. A deterministic offline eval (`pnpm eval:capture`) scores it — 42.9% naive JSON.parse vs 71.4% robust recovery over 14 real small-model reply shapes. - core: capture.ts (Markdown + obsidian:// builders), enrich.ts (prompt + tolerant parser); both fully unit-tested - ui: capture orchestrator + a "save to Obsidian" button on the translate panel - background: ENRICH_CAPTURE one-shot; api: enrichText (non-streamed) - settings + popup: vault name, capture folder, enrichment toggle - docs + eval harness updated 85 unit tests pass; pure-core coverage 100% funcs / ~94% lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0Smallcat0
force-pushed
the
feat/obsidian-capture
branch
from
July 9, 2026 10:13
db9dd88 to
5bc2bed
Compare
CI pinned pnpm to v9, which cannot read pnpm 11's `allowBuilds` build-script approval in pnpm-workspace.yaml and died at `pnpm store path` with "packages field missing or empty" before install ran (this affected main too). Bump pnpm/action-setup to v11 and setup-node to Node 22 (pnpm 11 requires Node >= 22.13 for node:sqlite; matches local dev). Drop the deprecated onlyBuiltDependencies key and align engines.node to >= 22. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0Smallcat0
force-pushed
the
feat/obsidian-capture
branch
from
July 9, 2026 10:14
5bc2bed to
694fb15
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds an optional capture-to-Obsidian bridge on top of the existing translation flow. Once a selection is translated, a + 儲存到 Obsidian button writes a Markdown note straight into an Obsidian vault via an
obsidian://newURI.Deliberately a thin bridge, not an Obsidian Web Clipper clone — the weight is on the handoff contract and an eval-backed local-enrichment stage, not the save button.
Design
obsidian://newfrom the content script (reusing the user gesture); oversized notes fall back to the clipboard. The least-privilege manifest (storage,activeTab) is unchanged.status: raw. On-device small models are unreliable at structured output, so OpenRead ships a reliable raw note and defers heavy synthesis to a stronger downstream "second brain" that flips the flag.parseEnrichResponsesalvages usable metadata from fenced, preamble-wrapped, and trailing-prose replies.Eval
pnpm eval:capture— deterministic and offline, over 14 real small-model reply shapes:JSON.parseyields an objectparseEnrichResponseyields usable metadataFull report in
eval/CAPTURE-RESULTS.md.Also: CI fix
CI was pinned to pnpm v9, which cannot read pnpm 11's
allowBuildsbuild-script approval inpnpm-workspace.yamland was failing atpnpm store pathbefore install even ran (this affectedmaintoo). Bumpedpnpm/action-setupto v11 to match local dev; dropped the deprecatedonlyBuiltDependencieskey.Gates (fresh install, pnpm 11)
pnpm install --frozen-lockfileexit 0 ·pnpm compileclean ·pnpm test85 pass (+28) ·pnpm lintclean ·pnpm buildok🤖 Generated with Claude Code