
Lit Sync
- 44 installs
- 236 repo stars
- Updated August 3, 2026
- aperivue/medsci-skills
Lit-sync is a Claude Code skill that syncs .bib references into a Zotero library and Obsidian literature notes and refreshes the manuscript refs.bib snapshot.
About
Lit-sync is a Claude skill that synchronizes research references from .bib files into a Zotero library and Obsidian literature notes. It parses BibTeX entries, deduplicates and adds them to a Zotero collection, refreshes the manuscript refs.bib snapshot, and creates per-reference notes. When enough literature notes accumulate it extracts cross-cutting concept notes.
- Syncs .bib references into Zotero and Obsidian literature notes
- Triggers Better BibTeX auto-export to refresh manuscript/_src/refs.bib
- Extracts cross-cutting concept notes once >=10 literature notes accumulate
Lit Sync by the numbers
- 44 all-time installs (skills.sh)
- Ranked #1,120 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
lit-sync capabilities & compatibility
- Capabilities
- manage refs · verify refs · meta analysis
- Works with
- notion · obsidian
- Use cases
- documentation · research
What lit-sync says it does
Takes the `.bib` output of `/search-lit` (or any user-specified .bib file) and
≥10 literature notes → scan for cross-cutting concepts → propose concept notes
npx skills add https://github.com/aperivue/medsci-skills --skill lit-syncAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 44 |
|---|---|
| repo stars | ★ 236 |
| Last updated | August 3, 2026 |
| Repository | aperivue/medsci-skills ↗ |
What it does
A researcher runs it after a literature search to register a .bib file into Zotero and Obsidian and refresh the manuscript reference snapshot.
Who is it for?
Registering a .bib file into Zotero and Obsidian and keeping the manuscript refs.bib in sync.
Skip if: Rendering the bibliography into a manuscript or auditing citation correctness.
When should I use this skill?
After a literature search completes, or to bulk-register an existing .bib into Zotero and Obsidian.
What you get
Deduplicated references added to a Zotero collection, a refreshed refs.bib snapshot, and per-reference Obsidian notes.
- Zotero collection sync
- references/zotero_collection.json
- Obsidian literature notes
By the numbers
- 4-phase pipeline
- >=10 literature notes triggers concept extraction
Files
Literature Sync: Zotero + Obsidian Pipeline
Takes the .bib output of /search-lit (or any user-specified .bib file) and synchronizes the references into the Zotero library and Obsidian literature notes. When enough literature notes accumulate, extracts cross-cutting concept notes.
Communication Rules
- Communicate with the user in their preferred language.
- Vault layout — honor what exists, default to English. Before creating notes, detect the
vault's existing layout: if the vault already uses a particular folder structure (including a Korean one such as 02 연구/문헌/ and 02 연구/개념노트/), honor it — never silently rename a user's folders. For a new or unclear vault, default to the English folders Literature/ and Concepts/ with the English note templates below.
- A Korean opt-in variant (Korean folder layout + Korean-heading templates) lives in
references/locale/ko/note_templates.md — use it when the vault is Korean-structured or the user prefers Korean notes.
When to Use
- After
/search-litcompletes — sync the produced .bib into Zotero + Obsidian. - Bulk-register references from an existing .bib into Zotero + Obsidian.
- Tidy the
references/folder inside a project workspace. - On explicit concept-extraction request → extract cross-cutting concepts from existing literature notes.
Prerequisites
- Project owner only —
/lit-syncis an owner-scoped operation perdocs/zotero_policy.md. Collaborators consume the committedmanuscript/_src/refs.bibsnapshot read-only. - Zotero desktop 7.x + Better BibTeX plugin installed.
- Better BibTeX "Keep updated" auto-export configured to
<project>/manuscript/_src/refs.bib(owner setup checklist indocs/zotero_policy.md§Setup). - Zotero MCP server available (skip the Zotero phase if not connected; auto-export refresh still fires once Zotero is reopened).
- Obsidian CLI or direct file writing to the Obsidian vault.
- Obsidian vault path: configured in user's environment (e.g.,
$OBSIDIAN_VAULT).
Artifact Contract
Per docs/artifact_contract.md, /lit-sync is the sole writer of:
| Artifact | Writer | Readers |
|---|---|---|
manuscript/_src/refs.bib | /lit-sync (via Better BibTeX auto-export trigger) | /write-paper, /verify-refs, /render |
references/zotero_collection.json | /lit-sync | /verify-refs, /sync-submission |
Direct hand edits to refs.bib are drift — revert on sight.
Pipeline Overview
.bib file (or /search-lit output)
│
▼ Phase 1: Parse
Extract DOI, PMID, title, authors, journal, year
│
▼ Phase 2: Zotero Sync (owner)
Dedupe → zotero_add_by_doi → place in collection → pin citekey
│
▼ Phase 2.5: refs.bib snapshot refresh
Trigger Better BibTeX auto-export → verify manuscript/_src/refs.bib mtime updated
│
▼ Phase 3: Obsidian Literature Notes
Create Literature/{citekey}.md (empty note OK — fill later with highlights)
│
▼ Phase 4: Concept Extraction (conditional)
≥10 literature notes → scan for cross-cutting concepts → propose concept notes---
Phase 1: Parse BibTeX
Input
The user-specified .bib file path, or the .bib just produced by /search-lit.
Process
# Parse .bib entries with regex.
# Extract per entry:
# - citekey (e.g., Kim_2024_Validation)
# - doi
# - pmid
# - title
# - authors (first + last minimum)
# - journal
# - year
# - volume, number, pages (if present)Log any parse failures and skip those entries.
---
Phase 2: Zotero Sync
Step 2.1: Determine project collection
Identify the project from the current working directory or from an explicit user override. Reuse an existing collection key if one is recorded; otherwise create a new collection.
Collection mapping: Check existing Zotero collections for the current project. If no collection exists, create one with zotero_create_collection. Record the collection key for future use.
Step 2.2: Dedupe + add
For each entry:
1. Use zotero_search_items to search by DOI or title — if already present, skip. 2. Otherwise call zotero_add_by_doi (when a DOI is available) or zotero_add_by_url (falling back to the PubMed URL when no DOI is available). 3. Use zotero_manage_collections to place the item in the project collection.
Step 2.3: Result report
Zotero Sync:
Added: 8 papers (new)
Skipped: 3 papers (already in library)
Failed: 1 paper (no DOI/PMID)
Collection: RFA-Meta (TZQEP4NH)If the Zotero MCP is not connected, skip this entire phase and proceed to Phase 3.
Always write references/zotero_collection.json in the project workspace:
{
"schema_version": 1,
"status": "synced",
"collection": "RFA-Meta",
"collection_key": "TZQEP4NH",
"added": 8,
"skipped": 3,
"failed": 1
}If Zotero is unavailable, write the same file with status: "skipped" and a human-readable reason.
---
Phase 2.5: refs.bib snapshot refresh
Better BibTeX "Keep updated" auto-export normally refreshes manuscript/_src/refs.bib within seconds of a Zotero change. This phase verifies the snapshot actually updated before downstream skills consume it.
Step 2.5.1: Resolve path
Read SSOT.yaml → truth.refs_bib. Default: manuscript/_src/refs.bib. If absent (legacy project), fall back to manuscript/_src/refs.bib and emit a WARN recommending SSOT migration.
Step 2.5.1b: Precondition assertion (early-exit, do NOT poll)
Before entering the 10s polling loop in Step 2.5.2, verify both preconditions. If either fails, abort Phase 2.5 with setup instructions instead of waiting for a timeout that will never resolve.
1. BBT auto-export registered. ~/Zotero/better-bibtex/read-only.json must be a non-empty JSON list. Check with:
python3 -c 'import json,sys,pathlib; p=pathlib.Path.home()/".zotero"/"zotero"/"Profiles"; \
f=pathlib.Path.home()/"Zotero"/"better-bibtex"/"read-only.json"; \
sys.exit(0 if f.exists() and json.loads(f.read_text() or "[]") else 1)'Or equivalent shell: [ -s ~/Zotero/better-bibtex/read-only.json ] && [ "$(jq 'length' ~/Zotero/better-bibtex/read-only.json)" -gt 0 ].
On failure print:
Phase 2.5 skipped: BBT auto-export not configured (~/Zotero/better-bibtex/read-only.jsonis empty or missing). Set up "Keep updated" auto-export perdocs/zotero_policy.md§Setup, then re-run/lit-sync.
2. Target refs.bib exists. The resolved truth.refs_bib path from Step 2.5.1 must exist on disk (even empty is OK — BBT will overwrite). On failure print:
Phase 2.5 skipped: target snapshot <path> not found. Configure BBT auto-export with "On Change" to the SSOT path, then re-run.In either early-exit, set refs_bib_refreshed: false + reason: "precondition:<which>" in the Step 2.5.3 JSON and return control to the caller. /verify-refs treats refs_bib_refreshed: false as an unverified snapshot — downstream skills (/write-paper, /render) block until the precondition is resolved.
Rationale (2026-04-24 Phase 1B-b dry-run): on a machine with BBT installed but no auto-export registered, the original Step 2.5.2 polled for 10s then emitted a generic "mtime unchanged" WARN that did not point at the actual cause. Findings: ~/.local/cache/phase1b_b_dryrun/findings.md.
Step 2.5.2: Verify refresh
After Phase 2 adds items:
1. Capture stat -f "%m" manuscript/_src/refs.bib before Zotero writes. 2. Wait up to 10s (Better BibTeX debounce). Poll mtime. 3. If mtime unchanged after 10s:
- Prompt user to check Zotero is running and BBT export is "Keep updated".
- If BBT auto-export path is wrong, print the expected path (
<project>/manuscript/_src/refs.bib) and refer todocs/zotero_policy.md§Setup. - As last resort, offer manual export:
File → Export Library → Better BibTeX → target path.
4. Once mtime advances, grep for the newly added citekeys. All must be present; if any is missing, report as failure (do NOT fabricate entries).
Step 2.5.3: Record in zotero_collection.json
Append to the JSON written in Step 2.3:
{
"refs_bib_path": "manuscript/_src/refs.bib",
"refs_bib_mtime": "2026-04-24T14:32:11Z",
"refs_bib_refreshed": true,
"citekeys_verified": ["Kim_2024_Validation", "..."]
}If refresh failed, set refs_bib_refreshed: false and include reason. /verify-refs uses this flag to decide whether the snapshot is trustworthy.
---
Phase 3: Obsidian Literature Notes
Step 3.1: Check existing literature notes
# Default English layout; substitute the vault's existing folder if one is present
# (e.g. "02 연구/문헌/" for a Korean-structured vault — see references/locale/ko/note_templates.md).
ls "$VAULT/Literature/" | grep -v "📊" | wc -lStep 3.2: Create literature notes
For each .bib entry, create Literature/{citekey}.md (or the vault's existing literature folder). Skip if the file already exists (never overwrite).
Template
---
notetype: literature
citekey: "{citekey}"
title: "{title}"
authors: "{authors}"
journal: "{journal}"
year: {year}
doi: "{doi}"
pmid: "{pmid}"
created: "{today}"
tags:
- type/literature
- _unread
---
# {title}
## Bibliographic info
- **Authors**: {authors}
- **Journal**: {journal}{volume_issue_pages}
- **Year**: {year}
- **DOI**: [{doi}](https://doi.org/{doi})
{pmid_line}
## Key points (in my own words)
## My thoughts
## Related notes
- [[Research Hub]]
- [[Papers & Reviews]]
-
-(For a Korean-structured vault, use the Korean-heading template in references/locale/ko/note_templates.md and the vault's own hub-note names.)
Rules:
notetype: literature— compatible with the Zotero Integration template._unreadtag — change to_readlater after the user reads the PDF in Zotero and adds highlights.- Leave
## Key pointsand## My thoughtsblank — the user fills these in personally. ## Related notescontains 2 hub links + 2 empty slots (reserved for later concept-note linking).- If a PMID is available, add a PubMed link.
Step 3.3: Result report
Obsidian Literature Notes:
Created: 8 notes (new)
Skipped: 3 notes (already exist)
Location: Literature/
Total in vault: 12 literature notes---
Phase 4: Concept Extraction (conditional)
Trigger condition
Run this phase only when there are ≥10 literature notes in the vault. If fewer exist, print a status message like "N literature notes — concept extraction unlocks at ≥10" and stop.
Step 4.1: Cross-cutting concept scan
Read all files under Literature/*.md (or the vault's existing literature folder): 1. Extract keywords from each paper's title, journal, and tags. 2. Extract major concepts from the .bib entry titles. 3. Identify concepts that co-occur across ≥3 literature notes.
Step 4.2: Filtering (5 exclusion rules)
Exclude from concept candidates:
- Model names (GPT-4, Claude, etc.).
- Dataset names (MedQA, ImageNet, etc.).
- Journal names.
- Institution names.
- Generic technique names (too unspecific).
Whatever remains becomes a concept-note candidate.
Step 4.3: Draft concept note
Create Concepts/{concept name}.md (or the vault's existing concept-note folder):
---
title: "{concept name}"
type: concept
tags:
- concept
- {domain tag}
aliases:
- {alternative name}
related_papers:
- "[[{lit-note-1}]]"
- "[[{lit-note-2}]]"
- "[[{lit-note-3}]]"
status: 🌱Seedling
---
# {concept name}
## Definition (My Understanding)
> TODO: write in your own words
## Why it matters
{why the concept matters in this domain — AI supplies a draft}
## Per-paper perspectives
- **[[{lit-note-1}]]**: {this paper's angle}
- **[[{lit-note-2}]]**: {a different angle}
- **[[{lit-note-3}]]**: {comparison / complement}
## Related concepts
- [[{another concept}]]
## Open questions
- {open question 1}
- {open question 2}
## Related notes
- [[Research Hub]]
- [[{related project hub}]]
- [[{lit-note-1}]]
- [[{lit-note-2}]](For a Korean-structured vault, use the Korean-heading concept template in references/locale/ko/note_templates.md.)
Key rules:
- Keep the
## Definitionsection as a> TODOmarker — the 2nd-layer note only becomes
meaningful once the user writes the definition in their own words.
statusalways starts at🌱Seedling.- At least 4 wikilinks under
## Related notes(vault convention).
Step 4.4: Propose to the user
Concept-note candidates (≥3 papers cross-referenced):
1. {Concept A} (4 papers)
2. {Concept B} (3 papers)
3. {Concept C} (5 papers)
Create? (all / selected / skip)Create only after user confirmation. Auto-draft but always confirm.
---
Standalone Modes
This skill can run without a fresh .bib file.
Concept extraction only
On an explicit concept-extraction request, scan existing Literature/*.md (or the vault's existing literature folder) and run only Phase 4.
References tidy
On a "tidy this project's references" request, locate .bib files inside the workspace and run Phase 1–3.
Zotero sync only
On a "sync Zotero" request, diff the Zotero collection against the .bib file and add whatever is missing.
PMID-list ingestion (no .bib)
When the user supplies a list of PMIDs (e.g., from a HANDOFF or a colleague), resolve PMIDs to DOIs via PubMed esummary first, then enter Phase 2 with the DOIs:
PMIDS="12345,67890,..."
curl -s "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${PMIDS}&retmode=json" \
| jq -r '.result | to_entries[] | select(.key != "uids") | "\(.value.uid)\t\(.value.elocationid)\t\(.value.title)"'For each resolved DOI call zotero_add_by_doi (auto-dedup by DOI). For items already in the library (returned as "skipped" or detected via zotero_search_items by DOI), use zotero_manage_collections to attach them to the project collection without re-adding — re-adding by URL/PubMed-URL would bypass DOI dedup and create duplicates. Record both added and existing items in references/zotero_collection.json.
If a PMID has no DOI in PubMed (rare; older papers, non-indexed), fall back to zotero_add_by_url with the PubMed URL and mark the entry as no_doi: true.
---
Safety Rules
1. Never overwrite literature notes — the user may have added highlights or personal notes. 2. Never auto-fill `## Definition` of a concept note — keep the TODO marker; the essence of the 2nd-layer note is the user's own wording. 3. Skip Zotero for entries without a DOI — ask the user to add those manually. 4. Gracefully skip Zotero when the MCP is not connected — Obsidian notes are created independently; but do NOT hand-edit refs.bib to compensate (violates artifact contract). 5. Always record the collection key — report the key to the user when a new collection is created. 6. Never write `refs.bib` directly. Only Better BibTeX auto-export may write that file. If auto-export is broken, fix the Zotero setup rather than writing the file from this skill. 7. Owner-only execution. If the current user is a collaborator (no Zotero access per SSOT.yaml reference_manager.required_for), abort with instructions to flag [@NEW:topic] placeholders in the manuscript and notify the owner.
Anti-Hallucination
- Never fabricate DOIs, PMIDs, or citation metadata. All bibliographic data must come from the .bib file or API responses.
- Never auto-fill the "Definition (My Understanding)" section of concept notes. This must be written by the user.
- Never overwrite existing literature notes. User highlights and annotations may be present.
- If a DOI lookup fails, report the failure rather than guessing the metadata.
Korean (ko) locale — Obsidian vault layout + note templates
Opt-in Korean variant for /lit-sync. The skill defaults to English folder names(Literature/,Concepts/) and English note headings. Use this layout when the user's
Obsidian vault already follows a Korean structure (the skill honors an existing layout) or
when the user explicitly prefers Korean notes.
Vault folder layout (Korean)
- Literature notes:
02 연구/문헌/{citekey}.md - Concept notes:
02 연구/개념노트/{concept name}.md
# Step 3.1 — count existing literature notes
ls "$VAULT/02 연구/문헌/" | grep -v "📊" | wc -lLiterature note template (Korean headings)
---
notetype: literature
citekey: "{citekey}"
title: "{title}"
authors: "{authors}"
journal: "{journal}"
year: {year}
doi: "{doi}"
pmid: "{pmid}"
created: "{today}"
tags:
- type/literature
- _unread
---
# {title}
## 서지 정보
- **저자**: {authors}
- **저널**: {journal}{volume_issue_pages}
- **연도**: {year}
- **DOI**: [{doi}](https://doi.org/{doi})
{pmid_line}
## 핵심 내용 (내 언어로)
## 내 생각
## 관련 노트
- [[🗺️ 연구 종합]]
- [[🗺️ 논문과 리뷰]]
-
-- Leave
## 핵심 내용and## 내 생각blank — the user fills these in personally. ## 관련 노트contains 2 hub links + 2 empty slots (reserved for later concept-note linking).
Concept note template (Korean headings)
---
title: "{concept name}"
type: concept
tags:
- 🧠개념
- {domain tag}
aliases:
- {English/Korean alternative name}
related_papers:
- "[[{lit-note-1}]]"
- "[[{lit-note-2}]]"
- "[[{lit-note-3}]]"
status: 🌱Seedling
---
# {concept name}
## 정의 (My Understanding)
> TODO: write in your own words
## 왜 중요한가
{why the concept matters in this domain — AI supplies a draft}
## 논문별 관점
- **[[{lit-note-1}]]**: {this paper's angle}
- **[[{lit-note-2}]]**: {a different angle}
- **[[{lit-note-3}]]**: {comparison / complement}
## 관련 개념
- [[{another concept}]]
## 열린 질문
- {open question 1}
- {open question 2}
## 관련 노트
- [[🗺️ 연구 종합]]
- [[{related project hub}]]
- [[{lit-note-1}]]
- [[{lit-note-2}]]- Keep the
## 정의section as a> TODOmarker — the 2nd-layer note only becomes meaningful once the user writes the definition in their own words. - Never auto-fill
## 정의of a concept note — keep the TODO marker. - At least 4 wikilinks under
## 관련 노트(vault convention).
schema_version: 2
name: lit-sync
layer: A
owner_domain: zotero_sync
maturity: official
when_to_use:
- User wants to add PMIDs / DOIs / Zotero collection items to the project library
- After /search-lit when verified candidates need to flow into Zotero + refs.bib
- Cross-cutting concept-note extraction from accumulated literature into Obsidian
- Refreshing manuscript/_src/refs.bib via Better BibTeX auto-export before a build
when_NOT_to_use:
- Pure literature search without sync (use /search-lit)
- Hand-editing refs.bib (BBT is the sole writer; never touch the file directly)
- Reference verification audit (use /verify-refs)
inputs:
- references/library.bib # search-lit candidate pool (optional)
- PMID list, DOI list, or Zotero collection name
outputs:
- references/zotero_collection.json
- manuscript/_src/refs.bib # SOLE WRITER via Better BibTeX auto-export "Keep updated"
- obsidian_literature_notes
deterministic_scripts:
- none_required # leverages Zotero MCP + Better BibTeX auto-export GUI
side_effects:
- may_update_zotero
- may_write_obsidian_notes
- refreshes_manuscript_refs_bib # via BBT auto-export
downstream_consumers:
- write-paper
- verify-refs
- manage-refs # consumes refreshed refs.bib for citekey validation + CSL render
ssot_boundary:
- SOLE writer of manuscript/_src/refs.bib. write-paper, manage-refs, verify-refs are read-only consumers.
quality_gates:
- refs_bib_refreshed: refs.bib mtime newer than collection snapshot in zotero_collection.json
- bbt_auto_export_active: Better BibTeX "Keep updated" must be ON for the project collection (verified per ~/.claude/rules/zotero-workflow.md)
forbidden_actions:
- fabricate_bibliographic_metadata
- overwrite_existing_literature_notes
- hand_edit_manuscript_refs_bib # only Better BibTeX may write
# v2.1 quality card
purpose: "Sync verified references from .bib into Zotero and Obsidian literature notes, extracting cross-cutting concept notes when enough literature accumulates."
safety_boundaries:
- "Bibliographic metadata is never fabricated; only Better BibTeX may write refs.bib."
- "Existing literature notes are not overwritten."
known_limitations:
- "Depends on a connected Zotero MCP + Better BibTeX auto-export; degrades to manual without them."
- "No standalone demo; effects are in the user's Zotero/Obsidian."
validation_commands:
- "confirm refs.bib mtime refreshed via Better BibTeX"
- "zotero_find_duplicates after sync"
evidence_surface: manual_workflow
#!/usr/bin/env bash
# Regression test for /lit-sync Phase 2.5 mtime-polling logic.
#
# Four synthetic scenarios (origin: ~/.local/cache/phase1b_b_dryrun/ dry-run,
# 2026-04-24). Runs in an isolated tmpdir; does not touch any real Zotero or
# project files. macOS (stat -f) and Linux (stat -c) compatible.
#
# Usage: bash skills/lit-sync/tests/test_poll_logic.sh
# Exit: 0 all pass, 1 any scenario fails.
set -u
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
# Inline poll script — same logic shipped with lit-sync Phase 2.5 guidance.
POLL="$TMP/poll.sh"
cat > "$POLL" <<'POLL_EOF'
#!/usr/bin/env bash
TARGET="$1"
TIMEOUT="${2:-10}"
if stat -f "%m" /dev/null >/dev/null 2>&1; then
STAT_CMD='stat -f %m'
else
STAT_CMD='stat -c %Y'
fi
BEFORE=$($STAT_CMD "$TARGET")
START=$(date +%s)
while true; do
NOW=$($STAT_CMD "$TARGET")
if [[ "$NOW" != "$BEFORE" ]]; then
ELAPSED=$(( $(date +%s) - START ))
echo "DETECTED mtime change after ${ELAPSED}s"
exit 0
fi
if (( $(date +%s) - START >= TIMEOUT )); then
echo "TIMEOUT after ${TIMEOUT}s"
exit 1
fi
sleep 0.5
done
POLL_EOF
chmod +x "$POLL"
PASS=0
FAIL=0
run_scenario() {
local name="$1" window="$2" write_at="$3" expected_exit="$4"
local bib="$TMP/refs_${name//[^a-z0-9]/_}.bib"
echo "@misc{test, title={x}}" > "$bib"
# Age the file so mtime isn't "now" (macOS second-granularity could cause
# the initial BEFORE to match a sub-second later write).
touch -t 202001010000 "$bib"
if [[ "$write_at" != "none" ]]; then
( sleep "$write_at" && echo "@misc{test, title={y}}" > "$bib" ) &
WRITER_PID=$!
else
WRITER_PID=""
fi
"$POLL" "$bib" "$window" >/dev/null
local actual=$?
[[ -n "$WRITER_PID" ]] && wait "$WRITER_PID" 2>/dev/null
if [[ "$actual" == "$expected_exit" ]]; then
echo " PASS [$name] exit=$actual (expected $expected_exit)"
PASS=$((PASS+1))
else
echo " FAIL [$name] exit=$actual (expected $expected_exit)"
FAIL=$((FAIL+1))
fi
}
echo "Phase 2.5 polling regression (4 scenarios)"
echo " Tmpdir: $TMP"
echo
# 1. BBT write within window → detect
run_scenario "detect-within-window" 10 3 0
# 2. No write, short window → timeout
run_scenario "timeout-silent" 3 none 1
# 3. BBT debounce, late-but-within write → detect
run_scenario "debounce-late" 10 8 0
# 4. Slow BBT, write outside window → timeout (Phase 2.5 fallback prompt)
run_scenario "slow-bbt-timeout" 4 8 1
echo
echo "Summary: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]
Related skills
FAQ
What does lit-sync require?
Zotero desktop 7.x with the Better BibTeX plugin, a Zotero MCP server, and an Obsidian vault; if Zotero MCP is not connected it skips that phase.
When does it extract concept notes?
When at least 10 literature notes have accumulated, it scans for cross-cutting concepts and proposes concept notes.