--- name: source-tracker description: "Persistent citation database for multi-session research. Add URLs as they're cited, dedup variants, tag by topic, check link health, and export bibliographies in Markdown/BibTeX/CSV/JSON." version: 1.0.0 author: moonlight-lupin license: MIT platforms: [linux, macos, windows] metadata: tags: [citation, bibliography, research, sources, dedup, url-tracking, link-health] related_skills: [deep-research, notebooklm-mode, entity-research] --- # Source Tracker ## Overview Source Tracker is a small persistent citation manager for research workflows. Research sources often scatter across browser tabs, notes, temporary files, and separate sessions. URLs get cited once and then disappear, duplicates accumulate as `http`/`https` or `www` variants, and bibliography export becomes a manual cleanup job at the end. This skill fixes that by keeping a portable SQLite database of every cited URL: add sources as soon as they are cited, tag them by topic, deduplicate URL variants, re-check stale links, and export bibliographies in Markdown, BibTeX, CSV, or JSON. The database path is configurable with `--db-path` or the `SOURCE_TRACKER_DB` environment variable. If neither is set, commands use `./sources.db` relative to the current working directory. ## Quick Start From the skill directory: ```bash python scripts/source_db.py add --url URL --topic TOPIC ``` A practical example: ```bash python scripts/source_db.py add \ --url "https://example.org/report" \ --topic "battery supply chain" \ --title "Example Battery Report" \ --notes "Baseline market-size estimate" \ --type report ``` Use a persistent project database when research spans folders or sessions: ```bash export SOURCE_TRACKER_DB="$HOME/research/sources.db" python scripts/source_db.py add --url "https://example.org" --topic "market scan" ``` Or pass the path explicitly: ```bash python scripts/source_db.py --db-path "$HOME/research/sources.db" add --url "https://example.org" --topic "market scan" ``` ## Workflows ### 1. Add Sources Add every URL at the moment it becomes a cited source. Always include a topic. Use a source type when the material is not a normal web page. ```bash python scripts/source_db.py add \ --url "https://example.com/article#section" \ --topic "ai regulation" \ --title "Example Article" \ --notes "Defines the enforcement timeline" \ --type news \ --session-id "research-2026-07-06" ``` If `--title` is omitted, the script tries a best-effort GET request and parses ``. If that fetch fails, the source is still added with a blank title. Completion criterion: the command prints a JSON object with `inserted: true` for a new row or `inserted: false` for an exact canonical URL already in the DB. ### 2. Search Sources Search by topic and optional filters. Results are JSON so they can be piped into other tools. ```bash python scripts/source_db.py search --topic "ai regulation" ``` Filter by date range: ```bash python scripts/source_db.py search \ --topic "ai regulation" \ --from 2026-01-01 \ --to 2026-12-31 ``` Filter by source type and verification status: ```bash python scripts/source_db.py search \ --topic "ai regulation" \ --type report \ --verified true ``` Completion criterion: the JSON array contains only records matching the topic and filters. ### 3. Deduplicate URL Variants Run dedup after a research burst or before export. It merges common URL variants such as `http` vs `https`, `www.` vs bare host, fragment-only differences, and trailing slash differences. ```bash python scripts/source_db.py dedup ``` Completion criterion: the command prints a JSON summary with `merged_groups`, `removed_rows`, and `removed_ids`. The survivor keeps the earliest `accessed_at` and combines non-empty notes from all merged rows. ### 4. Export Bibliographies Export a topic bibliography. If `--output` is omitted, content prints to stdout. If `--output` is set, provide the file path to the user. Markdown: ```bash python scripts/source_db.py export \ --topic "ai regulation" \ --format markdown \ --output ai-regulation-sources.md ``` BibTeX: ```bash python scripts/source_db.py export \ --topic "ai regulation" \ --format bibtex \ --output ai-regulation-sources.bib ``` CSV: ```bash python scripts/source_db.py export \ --topic "ai regulation" \ --format csv \ --output ai-regulation-sources.csv ``` JSON: ```bash python scripts/source_db.py export \ --topic "ai regulation" \ --format json \ --output ai-regulation-sources.json ``` Completion criterion: the output contains every source for the topic, sorted by topic/title/date, in the requested format. ### 5. Health Check Run link health checks manually before a final report or from a cron scheduler. The checker uses HEAD requests, marks HTTP 200-399 as alive, updates `last_checked`, and flags dead links by setting `verified = 0`. ```bash python scripts/url_health.py --stale-days 30 --timeout 10 --batch-size 50 ``` With an explicit database path: ```bash python scripts/url_health.py \ --db-path "$HOME/research/sources.db" \ --stale-days 7 \ --timeout 5 \ --batch-size 100 ``` Completion criterion: the command prints `Checked N URLs: M alive, K dead` and exits with code 0. Dead links are recorded in the database; they are not treated as runtime errors. ### 6. Stats and Topic Inventory Show source counts by topic, type, and verification status: ```bash python scripts/source_db.py stats ``` List all topic tags: ```bash python scripts/source_db.py list-topics ``` Completion criterion: stats print as JSON and topic inventory prints a JSON array of distinct topic strings. ## URL Normalization Rules Source Tracker uses two levels of URL handling: 1. **Canonical storage URL** - Lowercase scheme and host. - Strip URL fragments such as `#section`. - Strip trailing slash on non-root paths. - Preserve query strings. - Preserve `www.` because it may be the URL the user expects to see. 2. **Dedup comparison key** - Applies all canonical storage rules. - Treats `http` and `https` variants as the same source. - Strips a leading `www.` prefix from the host for comparison only. Examples: | Input | Canonical URL | Dedup comparison | |---|---|---| | `HTTPS://WWW.Example.com/Page/#intro` | `https://www.example.com/Page` | `//example.com/Page` | | `http://example.com/` | `http://example.com/` | `//example.com/` | | `https://www.example.com` | `https://www.example.com/` | `//example.com/` | ## Source Types Use one of these values with `--type`: | Type | Use for | |---|---| | `web` | Standard web pages, documentation pages, blog posts, landing pages. | | `pdf` | Direct PDF URLs or pages where the source of record is a PDF. | | `api` | API endpoints, JSON/XML data endpoints, machine-readable service output. | | `dataset` | Data downloads, CSV/Parquet repositories, public data catalogs. | | `book` | Online books, book chapters, scans, or bibliographic pages for books. | | `news` | News articles, wire reports, interviews, live blogs. | | `report` | White papers, government reports, analyst reports, institutional reports. | ## Research Workflow Integration ### Deep Research During iterative search/extract/synthesize work, add a source immediately after it passes the quality filter and before using it in the synthesis: ```bash python scripts/source_db.py add \ --url "SOURCE_URL" \ --topic "PROJECT_TOPIC" \ --title "SOURCE_TITLE" \ --notes "Supports sub-question: ..." \ --session-id "SESSION_ID" ``` Before the final report: ```bash python scripts/source_db.py dedup python scripts/source_db.py export --topic "PROJECT_TOPIC" --format markdown --output bibliography.md ``` ### Notebook-style Source Vaults When building a source vault, add each source as it enters the vault. Store the vault or corpus identifier in `--session-id`, and use notes for coverage labels such as `primary evidence`, `background`, or `contradiction`. ```bash python scripts/source_db.py add \ --url "SOURCE_URL" \ --topic "VAULT_TOPIC" \ --notes "Vault source 007; primary evidence" \ --session-id "vault-007" ``` ### Entity Research For entity dossiers, tag sources with the entity name plus the research lens. Use source types to distinguish official registries, adverse media, reports, and datasets. ```bash python scripts/source_db.py add \ --url "SOURCE_URL" \ --topic "Acme Ltd adverse media" \ --type news \ --notes "Allegation source; not independently verified" ``` ## Cron Usage Run weekly health checks with the cron scheduler. Example crontab entry: ```cron 0 9 * * 1 cd /path/to/source-tracker && SOURCE_TRACKER_DB=/path/to/sources.db python scripts/url_health.py --stale-days 30 --batch-size 100 >> /path/to/source-health.log 2>&1 ``` Use small batches for very large databases to avoid long scheduler jobs: ```cron 0 9 * * 1 cd /path/to/source-tracker && python scripts/url_health.py --db-path /path/to/sources.db --stale-days 30 --batch-size 50 ``` ## Output Formats - **Markdown bibliography** — grouped by topic, with each source rendered as `- [Title](URL) — notes (accessed_at)`. - **BibTeX** — `@misc{key, title={...}, url={...}, note={...}, urldate={...}}`. - **CSV** — `id,url,title,topic,source_type,accessed_at,notes,verified,last_checked`. - **JSON** — array of full source objects, including `session_id` and normalized URL fields. See `references/export-formats.md` for concrete examples. ## Common Pitfalls 1. **Invented URLs** — never add a URL unless it came from a web search tool, web extraction tool, user-provided source, or another verifiable source channel. If a URL was guessed, verify it before adding it. 2. **Missing topic tags** — `--topic` is required for a reason. Use consistent topic names so search, stats, and export do not fragment across near-duplicates. 3. **Stale health checks** — `verified = 1` means the source was alive at its last check, not that it is alive forever. Run `url_health.py` before final delivery for long-running projects. 4. **Duplicate variants** — `https://www.example.com/`, `http://example.com`, and `https://example.com#intro` can refer to the same source. Run `dedup` before export. 5. **Blank titles** — title extraction is best-effort. For important citations, pass `--title` explicitly instead of relying on a remote page fetch. 6. **Relative database confusion** — the default `./sources.db` depends on the current working directory. Use `SOURCE_TRACKER_DB` or `--db-path` for long-running projects. ## Verification Checklist - [ ] Every cited URL was observed through a real source channel before adding. - [ ] Each added row has a meaningful `--topic` and appropriate `--type`. - [ ] `python scripts/source_db.py dedup` was run before bibliography export. - [ ] `python scripts/url_health.py` was run recently for final deliverables. - [ ] Exported bibliography uses the requested format and output path. - [ ] Dead or unverified links are reviewed before final citation use. - [ ] The database path is explicit for multi-session work (`--db-path` or `SOURCE_TRACKER_DB`).