Help us improve
Share bugs, ideas, or general feedback.
From spotlight
Archives investigation findings into a structured Markdown vault (Obsidian, Tolaria, or directory) as entity/methodology/tool notes with registries and wikilinks. Invoked via Spotlight pipeline or standalone.
npx claudepluginhub buriedsignals/spotlight --plugin spotlightHow this skill is triggered — by the user, by Claude, or both
Slash command
/spotlight:ingestThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are archiving confirmed investigation findings into a structured knowledge base.
Archives investigation findings into Obsidian vaults or directories as structured knowledge with entity notes, methodology notes, tool notes, registries, and wikilinks. Standalone or Spotlight pipeline.
Ingests files and URLs into an Obsidian vault by extracting entities and concepts, creating or updating wiki pages with cross-references. Supports batch mode and multiple transport methods (CLI, MCP, filesystem).
Runs 7-phase Obsidian vault audit: structural scan, duplicate detection, link integrity, frontmatter audit, MOC review, cross-agent checks, health report.
Share bugs, ideas, or general feedback.
You are archiving confirmed investigation findings into a structured knowledge base.
This skill instructs. You — the host runtime — execute. You read investigation files, write vault notes, update registries, and maintain the knowledge graph. The user sees the result; you do the work.
Two input modes:
The orchestrator passes project path and vault config (from .spotlight-config.json). All inputs are known:
vault_path — target vault or directoryvault_type — "obsidian", "tolaria", or "directory"project — project slugRead these case files:
{CASE_DIR}/data/findings.json
{CASE_DIR}/data/fact-check.json
{CASE_DIR}/data/investigation-log.json
{CASE_DIR}/data/summary.json
Skip to the Ingestion Process.
The user requests ingestion directly.
Step 1 — Findings source:
"Point me to your findings file (JSON with claims, sources, and evidence)."
read-file(<path>). Validate it contains a findings array where entries have sources. If the structure is wrong:
"This file doesn't match the expected format. I need a JSON file with a
findingsarray where each finding hasclaim,sources, andevidencefields."
STOP.
Step 2 — Vault target:
"Which vault or directory should I archive to?"
Check if the path contains .obsidian/:
list-files("{path}/.obsidian")
vault_type = "obsidian" — wikilinks enabled.vault_type = "tolaria" — keep tolaria; use Markdown files, YAML frontmatter, and wikilinks.vault_type = "directory" — relative markdown links.Step 3 — Supplementary files:
Check whether these exist alongside the findings file. Use whatever is available; do not require all of them:
fact-check.json — verdict annotationsinvestigation-log.json — methodology, tools, search queriessummary.json — overview and conclusionsProceed to the Ingestion Process with whatever files were found.
Before starting the ingestion process, check for a lock file:
list-files("{vault}/.ingest-lock")
If present:
"Another ingestion is in progress. Wait for it to complete before running again."
STOP. Do not proceed.
If absent:
Create the lock:
write-file("{vault}/.ingest-lock", "{project-id} {ISO timestamp}")
Remove the lock when ingestion completes — whether successful or failed. Always clean up:
execute-shell("python3 scripts/spotlight_safe.py destructive-probe --base {vault} --path .ingest-lock")
execute-shell("python3 scripts/spotlight_safe.py resolve-path --base {vault} --path .ingest-lock")
execute-shell("rm <resolved-lock-path-from-probe>")
If the process errors partway through, remove the lock before reporting the error.
Seven steps. Execute in order. Do not skip steps.
Read all registry files:
read-file("{vault}/_registry.json")
read-file("{vault}/investigations/_registry.json")
read-file("{vault}/entities/_registry.json")
read-file("{vault}/methodology/_registry.json")
read-file("{vault}/tools/_registry.json")
If the vault is empty (registries do not exist), initialize each with the empty schema from references/registry-spec.md and schema_version: "1.0". Create the directories:
{vault}/investigations/
{vault}/entities/
{vault}/methodology/
{vault}/tools/
write-file("{vault}/investigations/{project-id}.md", ...).
Frontmatter — per references/entity-model.md Investigation Note schema:
---
id: {project-id}
title: {from summary.json title, or derive from findings}
status: confirmed
date: {today YYYY-MM-DD}
regions: [{from findings}]
entities: [{entity IDs extracted in Step 3}]
methodology: [{technique IDs extracted in Step 4}]
tools: [{tool IDs extracted in Step 5}]
tags: [{derived from findings topics}]
verified_count: {count of high-confidence verified findings}
total_findings: {total findings count}
---
Body:
summary.json overview. If no summary.json, synthesize from findings.findings.json:
fact-check.json matching claim. If verdict is disputed or false, flag prominently: > **DISPUTED** — {reason} or > **FALSE** — {reason}[[entity-id]] for each entity involved.[[technique-id]], [[tool-id]].Extract entities from:
findings.json — connections[].from and connections[].tofindings.json — named entities in findings[].claim (apply basic NER: proper nouns, organization names, geographic names)Infer entity type:
| Pattern | Type |
|---|---|
| Person names (first + last) | person |
| Known organization patterns (UN, EU, ministry, commission, etc.) | organization |
| Company indicators (Inc, Ltd, GmbH, AG, SA, etc.) | company |
| Geographic names (countries, cities, regions) | place |
Generate kebab-case ID from entity name.
If entity exists in {vault}/entities/_registry.json (match on id):
read-file("{vault}/entities/{entity-id}.md")| [[{project-id}]] | {role description} | {date} |{project-id} to frontmatter investigations array (if not already present)write-file the updated noteIf entity is new:
write-file("{vault}/entities/{entity-id}.md", ...) per references/entity-model.md:
---
id: {entity-id}
type: {inferred type}
subtype: {if determinable, else omit}
aliases: [{alternate names found in findings}]
country: {if determinable}
region: {if determinable}
investigations: [{project-id}]
first_seen: {today YYYY-MM-DD}
---
Body: Description, Role in Investigations table (one row for this project), Key Relationships (wikilinks to other entities from same investigation).
Extract techniques from investigation-log.json:
cycles[].methodology.techniques_usedIf technique exists in {vault}/methodology/_registry.json:
read-file the existing note| [[{project-id}]] | {context} | {date} |cycles[].methodology.failed_approaches to "Lessons Learned" section{project-id} to frontmatter investigations arraywrite-file the updated noteIf technique is new:
write-file("{vault}/methodology/{technique-id}.md", ...) per references/entity-model.md:
---
id: {technique-id}
type: technique
category: {infer from technique name}
tools: [{tool IDs used with this technique}]
investigations: [{project-id}]
---
Body: Description, Steps (if inferable from log), Tools (wikilinked), Usage History table, Lessons Learned.
Extract tools from investigation-log.json:
cycles[].methodology.tools_usedIf tool exists in {vault}/tools/_registry.json:
read-file the existing noteusage_count in frontmattercycles[].methodology.search_queries only if they are not duplicates of existing advice{project-id} to frontmatter investigations arraywrite-file the updated noteIf tool is new:
write-file("{vault}/tools/{tool-id}.md", ...) per references/entity-model.md:
---
id: {tool-id}
type: tool
category: {infer from tool name}
url: {if known}
access: {if known, else omit}
methodology: [{technique IDs that use this tool}]
investigations: [{project-id}]
usage_count: 1
---
Body: Capabilities, Access Notes, Usage History table (one row), Tips for Future Agents (from search queries if useful).
This is mandatory. Update every registry affected by the ingestion.
{vault}/investigations/_registry.json — add or update the investigation entry.{vault}/entities/_registry.json — add new entities, update investigations arrays for existing ones.{vault}/methodology/_registry.json — add new techniques, update investigations arrays for existing ones.{vault}/tools/_registry.json — add new tools, update investigations and usage_count for existing ones.{vault}/_registry.json (master) — update stats counts and last_updated to current ISO 8601 timestamp.See references/registry-spec.md for exact schemas.
write-file("{vault}/_INDEX.md", ...) using the template from references/registry-spec.md.
For Obsidian and Tolaria vaults: use wikilinks in the investigations table ([[project-id]]).
For directory fallback: use relative links ([project-id](investigations/project-id.md)).
After Step 7 completes, remove the .ingest-lock.
When vault_type is "directory" (no .obsidian/ detected):
[[entity-id]] with relative markdown links [entity-id](../entities/entity-id.md).[[project-id]] with [project-id](../investigations/project-id.md).[[technique-id]] with [technique-id](../methodology/technique-id.md).[[tool-id]] with [tool-id](../tools/tool-id.md)._INDEX.md browse section uses relative links too.Frontmatter and registry JSON are identical regardless of vault type.
id. If it exists, update it.references/entity-model.md. Agents rely on it programmatically. Never omit or rename fields.[[entity-id]] format in Obsidian and Tolaria vaults for all cross-references.swiss-leaks, john-doe, reverse-image-search.> **LOW CONFIDENCE** — {reason} if included at all.For runtimes that provide a native vault-write(vault_path, note_path, content) verb, prefer it over raw write-file. The vault-write verb should handle:
.ingest-lock coordinationIf the adapter doesn't implement vault-write, fall back to the per-step write-file + read-file pattern described above.
Reads from:
{CASE_DIR}/data/findings.json
{CASE_DIR}/data/fact-check.json
{CASE_DIR}/data/investigation-log.json
{CASE_DIR}/data/summary.json
{vault}/_registry.json
{vault}/investigations/_registry.json
{vault}/entities/_registry.json
{vault}/methodology/_registry.json
{vault}/tools/_registry.json
Writes to:
{vault}/investigations/{project-id}.md
{vault}/entities/{entity-id}.md (per entity)
{vault}/methodology/{technique-id}.md (per technique)
{vault}/tools/{tool-id}.md (per tool)
{vault}/investigations/_registry.json
{vault}/entities/_registry.json
{vault}/methodology/_registry.json
{vault}/tools/_registry.json
{vault}/_registry.json (master)
{vault}/_INDEX.md