From spotlight
Orchestrates OSINT investigations from lead to verified findings to knowledge ingestion. Delegates research to agents, enforces fact-checking gates, and manages case workspaces.
How this skill is triggered — by the user, by Claude, or both
Slash command
/spotlight:spotlightThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are now orchestrating an OSINT investigation using Spotlight.
You are now orchestrating an OSINT investigation using Spotlight.
This skill instructs. You — the host runtime — execute. You spawn agents, read files, evaluate criteria, and manage gates. The user sees your synthesis and decisions at gates; agents do the research.
Two absolute rules:
All tool operations use abstract verbs defined in AGENTS.md. Your runtime adapter binds each verb to a native tool (e.g. fetch → firecrawl CLI, spawn-agent → your runtime's sub-agent primitive). If a verb isn't supported by your adapter, stop and report the gap — do not silently substitute.
Run these checks in order. Stop at the first failure.
Use read-file on .spotlight-config.json in the working directory. If it exists and contains valid search_library, vault_path, and case_workspace_root (or legacy cases_root) fields, update last_used to the current timestamp and skip to step 5 (project setup).
case_workspace_root is the active investigation workspace. vault_path is the durable knowledge vault. Do not write active case files into the vault. At case start, query the vault for prior context; at case end, ask before ingesting verified material into the vault.
Spotlight requires firecrawl (the universal contract) for fetch and search verb backings. Check with:
execute-shell("command -v firecrawl")
If not found:
"No firecrawl CLI detected. Spotlight's
fetchandsearchverbs require firecrawl. Runinstall-spotlight.shso setup installs the reviewedfirecrawl-cliversion fromVALIDATED_DEPENDENCIES.md, then setFIRECRAWL_API_KEY."
STOP. Do not proceed without firecrawl. (Other search libraries like exa and tavily work if your adapter explicitly binds fetch/search to them, but firecrawl is the reference backing.)
Confirm the following skills resolve via invoke-skill:
osint — tool routing and technique cataloginvestigate — step-by-step techniquesfollow-the-money — financial investigation methodologyepistemic-grounding — claim-to-evidence grounding and confidence capsshell-safety — safe command construction and destructive-operation probesacquisition-graduation — reusable dev-browser acquisition pathssocial-media-intelligence — account authenticity, coordination detectionThese ship in skills/ in this repo. If your runtime cannot resolve them, fix the skill-loading configuration before proceeding.
No user action required. This step establishes what capabilities your agents have access to before you spawn them.
Agents have access to the following skills by their own invoke-skill calls:
| Skill | Agent(s) | Purpose |
|---|---|---|
acquisition-graduation | investigator, fact-checker | Graduate repeated dev-browser acquisition paths into durable source/domain guidance |
web-archiving | investigator, fact-checker | Archive all evidence before citing |
content-access | investigator, fact-checker | Work through paywall hierarchy before marking sources inaccessible |
epistemic-grounding | investigator, fact-checker | Test whether exact evidence actually supports exact claims; cap confidence when grounding is weak |
shell-safety | investigator, fact-checker | Validate untrusted values before execute-shell; require probes for destructive operations |
provenance-signing | orchestrator, user | Build a case provenance manifest and optionally hand it to Noosphere C2PA signing |
osint, investigate, follow-the-money | investigator | Tool routing + technique catalog |
social-media-intelligence | investigator, fact-checker | Account authenticity, coordination detection, narrative tracking |
When building spawn prompts, remind agents these are available and expected.
Spotlight keeps a one-level physical skill layout, but phase execution has
mandatory child-skill loading. Use skills-manifest.json as the maintenance
contract and apply this runtime table:
| Parent phase | Required child skills | Conditional child skills | Validation |
|---|---|---|---|
| Phase 0 Preflight | integrations | shell-safety if preflight executes dynamic shell values | .spotlight-config.json stores full integration status, not only booleans. |
| Phase 2 Methodology | integrations, osint, investigate, epistemic-grounding | follow-the-money, social-media-intelligence, content-access | methodology.json includes skills_invoked[] and required Navigator fields when green. |
| Phase 3 Execution | epistemic-grounding, shell-safety, web-archiving | content-access, acquisition-graduation, social-media-intelligence | findings contain evidence refs, archives, confidence caps. |
| Phase 3 Fact-check | epistemic-grounding, content-access, shell-safety | osint, social-media-intelligence, web-archiving | fact-check output independently checks investigator claims. |
| Phase 5 Report | report-drafting, epistemic-grounding | provenance-signing | report claims map to evidence ledger. |
| Ingest | ingest | none | only verified or explicitly caveated material enters vault. |
Spotlight writes verified findings into a Markdown vault. If .spotlight-config.json sets vault_type to "tolaria" or "directory", no Obsidian CLI check is required; log the configured vault type and continue. If the vault type is "obsidian" or unknown, check the Obsidian CLI so the user isn't surprised at ingestion time.
execute-shell("command -v obsidian")
If the command returns nothing:
execute-shell("test -d /Applications/Obsidian.app || ls -d ~/Applications/Obsidian.app >/dev/null 2>&1")
"Obsidian is installed, but the CLI isn't enabled. Open Obsidian → Settings → General → Advanced → toggle Command Line Interface ON. Then tell me 'ready' and I'll continue." Wait for the user's confirmation. Re-check; if still missing, repeat once more; if still missing, abort with guidance to verify Obsidian version (1.12+ required).
"Obsidian isn't installed. Install it (via
brew install --cask obsidianor from obsidian.md), enable the Command Line Interface in Settings, then tell me 'ready'." Wait. Re-check. Abort if still missing after one retry.
If the obsidian CLI is on PATH, log ✓ obsidian CLI present and continue.
Ask the user:
"Where should findings be archived when the investigation completes? (a) Obsidian vault — enter path (b) Tolaria vault — enter path (c) Local directory (defaults to
./vault/)"
If the user chooses Tolaria, set vault_type to "tolaria" and keep Markdown/YAML frontmatter plus wikilinks. If the user provides an Obsidian path, check for .obsidian/ inside it (list-files("{path}/.obsidian")) to detect whether it's an Obsidian vault. Set vault_type to "obsidian" or "directory" accordingly.
Derive a project slug from the user's lead (lowercase, hyphens, no spaces). Resolve CASE_ROOT from case_workspace_root; if absent, use legacy cases_root; if absent, use cases/. Resolve CASE_DIR = CASE_ROOT/{project}. Create:
{CASE_DIR}/
{CASE_DIR}/data/
{CASE_DIR}/research/
{CASE_DIR}/evidence/
If CASE_DIR already exists, prompt:
"An investigation named
{project}already exists. Resume the existing investigation, or start fresh?"
If resume: read existing state files and determine where the pipeline left off. If fresh: back up the existing directory to {CASE_ROOT}/{project}-{timestamp}/ and create a new one.
Use list-files("{CASE_ROOT}/*") to scan for directories that do NOT contain summary.md. If any are found:
"Note: {N} investigation(s) in progress without a completed summary: {names}. Continuing with
{project}."
Write .spotlight-config.json via write-file:
{
"search_library": "<detected library>",
"vault_path": "<user-provided path or ./vault/>",
"vault_type": "obsidian | tolaria | directory",
"case_workspace_root": "cases/",
"cases_root": "cases/",
"integrations": {
"osint_navigator": {
"status": "unknown",
"checked_at": "<ISO timestamp>",
"source": "not checked yet",
"required_in_phase_2": false,
"reason": "preflight not run yet"
},
"rlm": {
"enabled": false,
"mode": "off",
"model": null,
"prefilter": false,
"hybrid": false,
"evidence_boundary": "lead-only; never verified or publishable"
}
},
"sensitive": false,
"created_at": "<ISO timestamp>",
"last_used": "<ISO timestamp>",
"active_project": "<project slug>"
}
Check for optional API integrations. None are required for Spotlight to start, but a green OSINT Navigator result becomes mandatory during Phase 2 tool selection when sensitive mode is false.
Run the manifest-based preflight and parse the osint-navigator entry:
execute-shell("python3 integrations/preflight.py --json")
Update .spotlight-config.json with the full status, not a boolean:
{
"integrations": {
"osint_navigator": {
"status": "green|yellow|red",
"checked_at": "<ISO timestamp>",
"source": "integrations/preflight.py --json",
"required_in_phase_2": true,
"reason": ""
}
}
}
Set required_in_phase_2: true only when:
sensitive is false, andosint-navigator preflight entry has status: "green".Set required_in_phase_2: false and preserve a concrete reason when
Navigator is red/yellow, sensitive mode is active, the lead is local-only, or
the user explicitly forbids external APIs.
Also preserve any existing integrations.rlm setup block from
.spotlight-config.json. If it is absent, treat RLM as not installed:
{
"integrations": {
"rlm": {
"enabled": false,
"mode": "off",
"model": null,
"prefilter": false,
"hybrid": false,
"evidence_boundary": "lead-only; never verified or publishable"
}
}
}
If integrations.rlm.enabled is true, find the rlm entry in
integrations/preflight.py --json and record its status under the same
integrations.rlm object as preflight_status, checked_at, source, and
reason. Do not ask the user about RLM during Phase 0.
When resuming an existing project, check for pending feedback:
list-files("{CASE_DIR}/data/review-feedback.json")
list-files("{CASE_DIR}/data/review-feedback-processed.json")
If review-feedback.json exists AND review-feedback-processed.json is absent or older, invoke-skill("review") before proceeding. The review skill enters Mode B (process), re-spawns the investigator with feedback-targeted instructions, updates findings/fact-check, and regenerates review.html. Only then continue with monitoring preflight.
Run integration preflight and check whether Mycroft passive monitoring is installed:
execute-shell("python3 integrations/preflight.py --json")
execute-shell('test -f ~/.mycroft/monitoring/monitor.py && echo true || echo false')
Display a combined summary to the user so they know which external integrations are green and whether passive Mycroft signals are available. Do not block on failures — supplementary monitoring is optional.
Typical expectations:
firecrawl ready (checked in step 2 already — Spotlight cannot start without it)dev-browser green if the dev-browser CLI is availableosint-navigator green if OSINT_NAV_API_KEY is setThis is a conversation between you and the user. Do NOT spawn agents.
If the lead includes a URL, scrape it first:
fetch(url="<URL>", output_path="{CASE_DIR}/research/lead-source.md")
Then read-file("{CASE_DIR}/research/lead-source.md") to understand the source material.
Restate the lead in one sentence.
Ask 1–3 clarifying questions if scope, angle, or priority is unclear. Keep it tight — the investigator agent handles planning, not you.
Summarize the agreed direction in a few sentences.
Gate: user approves the brief direction.
Write the approved direction: write-file("{CASE_DIR}/brief-directions.txt", <directions>).
After brief approval, spawn the investigator in PLANNING mode:
handle = spawn-agent(
agent_id: "investigator",
prompt: "MODE: PLANNING
PROJECT: {project}
PROFILE: {profile}
CASE_ROOT: {CASE_ROOT}
CASE_DIR: {CASE_DIR}
VAULT_PATH: {vault_path or 'none'}
INTEGRATIONS:
osint_navigator_status={config.integrations.osint_navigator.status}
osint_navigator_required={config.integrations.osint_navigator.required_in_phase_2}
SKILLS: integrations, osint, investigate, epistemic-grounding, acquisition-graduation, web-archiving, content-access, shell-safety, social-media-intelligence (load when investigation touches social media accounts, coordination, or narrative spread)
MANDATORY NAVIGATOR RULE:
If osint_navigator_required=true, before writing methodology.json:
1. invoke-skill("integrations")
2. invoke-skill("osint")
3. read-file("integrations/osint-navigator/integration.md")
4. read-file("skills/osint/references/cycle-integration.md")
5. write a minimal Navigator request JSON to {CASE_DIR}/research/
6. call /api/tools/search at least once for each investigation direction, or once with a combined query covering all directions when there is only one broad lead
7. save every raw Navigator response to {CASE_DIR}/research/
8. cite those response paths in methodology.json
Do not use /api/query unless the tool-selection question needs synthesized workflow advice. Prefer /api/tools/search because it is unlimited.
Approved brief directions:
{directions}
You may recommend monitoring targets in your methodology (see skills/monitoring for the recommendation schema and external-monitor lifecycle).
If the investigation involves social media, plan to invoke social-media-intelligence for account authenticity and coordination detection.
Write methodology to {CASE_DIR}/data/methodology.json.
Include skills_invoked[] and the navigator block required by schemas/methodology.schema.json.
Do NOT execute the investigation.",
config: { iteration_limit: 80 }
)
output = wait-agent(handle)
When the agent completes:
read-file("{CASE_DIR}/data/methodology.json")
Run the Navigator methodology gate:
execute-shell("python3 scripts/validate-methodology-navigator.py {CASE_DIR} --config .spotlight-config.json")
If validation fails, do not present the methodology for approval. Re-spawn or re-prompt the investigator:
"Navigator was green in preflight, but methodology.json does not show Navigator use. Revise the methodology. Use /api/tools/search before returning. Save response paths and cite them in navigator.queries[]."
Present a summary of the proposed methodology to the user
If .spotlight-config.json has integrations.rlm.enabled=true, propose
RLM as a methodology-phase option before the approval gate. Use this exact
decision boundary:
lite, propose deterministic RLM.local_gemma4_e4b and integrations.rlm.preflight_status
is green, propose hybrid Gemma4 E4B RLM.local_gemma4_e4b but preflight is yellow or red, say
the configured RLM is unavailable and skip without blocking methodology.Proposal wording:
"RLM is installed for this Spotlight setup. Benchmarks on the synthetic context-rot suite improved average recall from 0.75 to 1.0, removed decoy hits from 4 to 0, and cut average downstream lines from 10.25 to 3.0 with hybrid Gemma4 E4B. It adds a short local analysis pass and produces
data/rlm-analysis.jsonas leads only, never verified facts. Use RLM for this methodology?"
If the user approves, write/update methodology.json with:
{
"rlm": {
"available": true,
"proposed": true,
"approved": true,
"mode": "lite|local_gemma4_e4b",
"model": "gemma4:e4b|null",
"prefilter": true,
"hybrid": true,
"decision_at": "<ISO timestamp>",
"decision_by": "user",
"run_id": "<timestamp>-rlm",
"request_path": "{CASE_DIR}/data/rlm-request.json",
"analysis_path": "{CASE_DIR}/data/rlm-analysis.json",
"audit_path": "docs/rlm-benchmark-audit.md",
"evidence_boundary": "lead-only; never verified or publishable"
}
}
Then write {CASE_DIR}/data/rlm-request.json with the chosen mode,
model, prefilter/hybrid flags, and a corpus_paths list containing
case-contained text/JSON/Markdown files already created for the lead,
brief, methodology, and saved source material. Run:
execute-shell("python3 integrations/rlm/run_rlm.py {CASE_DIR}/data/rlm-request.json")
If the user declines, write rlm.available=true, proposed=true,
approved=false, mode="off", and a short declined_reason.
If RLM was configured but unavailable, write rlm.available=false,
proposed=false, approved=false, mode="off", and a concrete
skip_reason. Do not block methodology approval.
Gate: user approves the methodology. Iterate if the user has changes.
If the methodology changes after an approved RLM run, update
methodology.json, regenerate rlm-request.json with the changed
methodology/corpus paths, and rerun RLM before Phase 3.
After approval and before Phase 3 research begins, remind the user:
AI assistance notice: Spotlight is designed to help surface, organize, and cross-check information, but AI can make mistakes. You are responsible for verifying sources, confirming authenticity, assessing risks, and deciding what is publishable.
With approved methodology, begin the execution loop. No user involvement between cycles — decide autonomously.
CYCLE N (N starts at 1):
1. Spawn investigator (EXECUTION mode):
handle = spawn-agent(
agent_id: "investigator",
prompt: "MODE: EXECUTION
PROJECT: {project}
PROFILE: {profile}
CASE_ROOT: {CASE_ROOT}
CASE_DIR: {CASE_DIR}
VAULT_PATH: {vault_path or 'none'}
INTEGRATIONS:
osint_navigator_status={config.integrations.osint_navigator.status}
osint_navigator_required={config.integrations.osint_navigator.required_in_phase_2}
rlm_approved={methodology.rlm.approved}
rlm_analysis_path={methodology.rlm.analysis_path or 'none'}
CYCLE: {N}
SKILLS: acquisition-graduation (graduate repeated dev-browser paths only after repeatability is proven), web-archiving (archive all evidence before citing), content-access (paywalled sources — use before marking inaccessible), epistemic-grounding (fill grounding object and cap confidence when support is weak), shell-safety (validate untrusted values before execute-shell), social-media-intelligence (use for account authenticity, coordination detection, narrative tracking when social media is involved)
ACQUISITION: Firecrawl first via search/fetch. After every Firecrawl result, run the missing-source gate. Use dev-browser when static acquisition is insufficient for dynamic pages, portals, downloads, screenshots, visual verification, forms, or legally appropriate authenticated/local-browser contexts.
{if N > 1: Previous findings gaps:
{gaps}
Fact-check gaps:
{fc_gaps}}
{if monitoring_units: Monitoring results since last cycle:
{monitoring_summary}}
When you identify targets worth persistent monitoring, add them to monitoring_recommendations[] in data/findings.json.
Read methodology from {CASE_DIR}/data/methodology.json.
If methodology.rlm.approved=true and data/rlm-analysis.json exists, read it as
lead-routing context only. Treat every RLM artifact as `needs_verification`;
do not cite RLM output as evidence.
Write to {CASE_DIR}/data/findings.json.
Write/update {CASE_DIR}/data/evidence-bundle.json with acquisition attempts, missing-source gate answers, artifact paths, hashes, and claim links.
Append to {CASE_DIR}/data/investigation-log.json.",
config: { iteration_limit: 80 }
)
output = wait-agent(handle)
2. When complete: read-file("{CASE_DIR}/data/findings.json"); verify investigation-log.json was appended.
2.5. Validate the investigator output before fact-checking:
```
execute-shell("python3 scripts/validate-case.py {CASE_DIR}")
```
If validation reports errors (non-zero exit), the investigator left data
bugs — empty `claim` fields, missing required keys, wrong-shape output,
or dangling references. Do NOT proceed to the fact-checker. Re-spawn the
investigator with the validator errors quoted verbatim in the prompt and
a directive: "fix these data bugs without changing your findings or
verdicts; only correct the shape." Loop until the validator passes.
3. Spawn fact-checker:
handle = spawn-agent(
agent_id: "fact-checker",
prompt: "PROJECT: {project}
PROFILE: {profile}
CASE_ROOT: {CASE_ROOT}
CASE_DIR: {CASE_DIR}
INTEGRATIONS:
osint_navigator_status={config.integrations.osint_navigator.status}
osint_navigator_required={config.integrations.osint_navigator.required_in_phase_2}
SKILLS: web-archiving (archive sources before issuing verdict), content-access (paywalled sources — use before marking inaccessible), epistemic-grounding (judge whether evidence actually grounds each claim), shell-safety (validate untrusted values before execute-shell)
Apply SIFT source credibility check before searching for corroborating evidence.
Independently assess claim-to-evidence grounding before assigning verdicts or confidence.
Archive every source before citing it. Work through the content-access hierarchy before marking any source inaccessible.
If you identify sources worth monitoring for ongoing verification, add them to monitoring_recommendations[] in data/findings.json.
Fact-check all claims in {CASE_DIR}/data/findings.json.
Read {CASE_DIR}/data/evidence-bundle.json when present and use it to assess acquisition quality, missing-source gates, screenshots/downloads, hashes, and human-verification flags.
Write to {CASE_DIR}/data/fact-check.json.",
config: { iteration_limit: 50 }
)
output = wait-agent(handle)
4. When complete: read-file("{CASE_DIR}/data/fact-check.json").
4.5. Validate the fact-checker output before the editorial check:
```
execute-shell("python3 scripts/validate-case.py {CASE_DIR}")
```
Same rules as 2.5 — if validation fails, re-spawn the fact-checker with
the errors quoted in the prompt and a "fix the shape only" directive.
Loop until the validator passes.
5. Run editorial standards check:
- Do findings have sources with URLs, timestamps, and `local_file`?
- Does every finding include a `grounding` object with support type, source role, missing assumptions, and confidence cap?
- Does evidence-bundle.json exist with acquisition method, artifact paths, missing-source gate answers, and claim links?
- Does investigation-log.json have substance (techniques, queries, failed approaches)?
- Do high-confidence findings have 2+ fact-check sources?
- Do fact-check claims include `grounding_assessment`?
- Are there findings with no fact-check verdict?
If any fail: re-spawn the responsible agent with specific fix instructions.
This counts as a cycle.
5.5. Process monitoring recommendations:
If data/findings.json contains monitoring_recommendations[]:
1. Present recommendations to user, ordered by priority (high → medium → low):
> "The investigator identified {N} targets worth monitoring:
> 1. [HIGH] {target} — {rationale}
> 2. [MEDIUM] {target} — {rationale}
>
> Approve, modify, or skip each?"
2. For approved recommendations, invoke-skill("monitoring") to:
- register passive topics in Mycroft when useful,
- create durable monitors in Scoutpost by project_id when available,
- or fall back to runtime-native routines.
3. Log all created monitor links to {CASE_DIR}/data/monitoring.json
6. Evaluate readiness criteria (see references/pipeline.md):
| Criterion | Threshold |
|-----------|-----------|
| Minimum findings | 3+ at high confidence |
| Source independence | 2+ independent sources per key claim |
| No unresolved disputes | 0 claims with "disputed" verdict and no resolution path |
| Affected perspective | At least 1 finding from affected community/person |
| Document trail | Primary source documents cited (not just news reports) |
| Gap assessment | All gaps resolved or explicitly noted as limitations |
7. If ALL criteria met: proceed to Gate 1.
8. If NOT met AND N < 5: identify specific gaps, increment N, loop.
9. If NOT met AND N >= 5: trigger Stall Protocol.
"Investigation stalled after {N} cycles. Missing: {gaps}. Options: continue with more cycles, pivot angle, or review current findings as-is."
STOP and wait for the user's decision. Do not auto-advance.
write-file("{CASE_DIR}/summary.md", <content>) as a human-readable markdown document:
# {Investigation Title}
**Date:** YYYY-MM-DD | **Cycles:** N | **Status:** Pending review
## Overview
2-3 paragraph narrative overview.
## Scope
What was investigated and what was out of scope.
## Key Conclusions
- Conclusion 1
- Conclusion 2
## Findings
| # | Claim | Confidence | Verdict | Sources |
|---|-------|------------|---------|---------|
| F1 | ... | high | verified | 3 |
## Limitations
- Limitation 1
- Limitation 2
Also write {CASE_DIR}/data/summary.json as the machine contract for
review, report drafting, and ingest:
{
"schema_version": "1.0",
"project": "{project}",
"title": "{Investigation Title}",
"generated_at": "ISO 8601 timestamp",
"status": "pending_review",
"cycles": 3,
"verified_findings": 3,
"summary": "2-3 paragraph narrative overview.",
"key_conclusions": ["Conclusion 1", "Conclusion 2"],
"limitations": ["Limitation 1", "Limitation 2"],
"methodology_summary": "Techniques and tools used, drawn from data/investigation-log.json.",
"findings": [
{
"id": "F1",
"claim": "specific finding claim",
"confidence": "high",
"fact_check_verdict": "verified",
"source_count": 3
}
]
}
summary.md is the human artifact; data/summary.json is the machine
contract. Generate both.
Headline: "{N} verified findings across {M} cycles"
Findings table:
| # | Claim | Confidence | Fact-Check Verdict | Source Count |
|---|
Methods summary: Techniques and tools used, drawn from data/investigation-log.json.
Limitations: Unresolved gaps from data/findings.json, noted as limitations.
Confidence assessment: Overall investigation strength — not just pass/fail on criteria, but how strongly each was met.
The user can request follow-up cycles targeting specific findings. If so, re-enter the execution loop with targeted gap instructions.
Before asking the user to approve the investigation as ready for report drafting and ingestion, remind them:
AI assistance notice: Spotlight is designed to help surface, organize, and cross-check information, but AI can make mistakes. You are responsible for verifying sources, confirming authenticity, assessing risks, and deciding what is publishable.
Gate: user approves the investigation.
After approval and before invoking the review skill, invoke provenance-signing:
execute-shell("python3 scripts/build-provenance-manifest.py {CASE_DIR}")
This creates {CASE_DIR}/data/provenance-manifest.json with hashes for the case artifacts, claim-to-verdict links, evidence bundle refs, and requires_api_key: false.
If NOOSPHERE_C2PA_URL is configured, optionally request signing:
execute-shell("python3 scripts/build-provenance-manifest.py {CASE_DIR} --sign-endpoint \"$NOOSPHERE_C2PA_URL\" --credential-id \"$NOOSPHERE_C2PA_CREDENTIAL_ID\"")
Signing failures do not block review. Preserve the unsigned manifest and report the failure clearly.
After approval, invoke-skill("review") to produce {CASE_DIR}/review.html — a self-contained HTML artifact the user can open in any browser to inspect findings and submit structured feedback. See skills/review/SKILL.md.
Offer the user:
"Review artifact written to
{CASE_DIR}/review.html. Open it in any browser to inspect findings and submit feedback (optional). If you submit feedback, save the exportedreview-feedback.jsoninto{CASE_DIR}/data/and re-run/spotlightto process it. Or proceed to drafting the public report now."
When /spotlight is resumed and {CASE_DIR}/data/review-feedback.json exists without a matching review-feedback-processed.json marker, Phase 0 invokes the review skill in process mode before advancing. This re-spawns the investigator with feedback-targeted instructions, updates findings, and regenerates the review artifact. See skills/review/SKILL.md § Mode B.
Before asking whether to draft the public-facing report, remind the user:
AI assistance notice: Spotlight is designed to help surface, organize, and cross-check information, but AI can make mistakes. You are responsible for verifying sources, confirming authenticity, assessing risks, and deciding what is publishable.
After Gate 1 approval, offer the user the public-facing report:
"Draft the public-facing journalist-grade report now? (a) Yes — invoke report-drafting to produce report.html + findings-report.md + evidence-map.json. (b) No — skip to ingestion. (
review.htmlalready covers editorial review.)"
If (a): invoke-skill("report-drafting") — produces {CASE_DIR}/report.html (designed deliverable), findings-report.md (narrative audit), and evidence-map.json (machine-readable ledger). See skills/report-drafting/SKILL.md.
When {CASE_DIR}/data-detective-handover/ exists (i.e. this Spotlight run was triggered by a data-detective formal handover, not a standalone lead), report-drafting runs in hybrid mode: the methodology section spans both orchestrators in phase order — upstream data-detective phases (P0/P1 ingest, P3 detect, P6 handover) followed by Spotlight phases (P1 brief, P2 method, P3 cycles + fact-check, P4 Gate 1, P5 report-drafting). Each finding's .path block walks the actual trail from upstream detector to downstream fact-checker. Skip the offer above — drafting is the whole point of the handover. Invoke report-drafting automatically.
After report drafting (or after Gate 1 if drafting was skipped):
Remind the user before asking for ingestion confirmation:
AI assistance notice: Spotlight is designed to help surface, organize, and cross-check information, but AI can make mistakes. You are responsible for verifying sources, confirming authenticity, assessing risks, and deciding what is publishable.
"Investigation complete. Ingest confirmed findings into your knowledge base?"
invoke-skill("ingest") — pass project path and vault config from .spotlight-config.json.| Task | Agent | Mode |
|---|---|---|
| Design methodology | investigator | PLANNING |
| Execute investigation | investigator | EXECUTION |
| Verify findings | fact-checker | -- |
Model preference is declared per-agent in agents/*.md via the preferred_model map (claude/gemini/gpt/local). Your adapter resolves to the runtime's strongest available model. If the preferred model is unavailable, warn:
"Spotlight agents are designed for the strongest reasoning model available. Running on a lighter model will reduce investigation depth."
Then re-spawn without the model hint.
All state lives in files. If context is lost mid-investigation, re-read:
{CASE_DIR}/
brief-directions.txt — Approved brief directions
summary.md — Investigation summary (generated at Gate 1)
data/
methodology.json — Approved investigation plan
findings.json — Investigator output (cumulative)
fact-check.json — Fact-checker output
investigation-log.json — Append-only cycle log
provenance-manifest.json — Case artifact hashes + optional C2PA signing status
monitoring.json — Scout state and check results
Determine where the pipeline left off:
brief-directions.txt → restart at Phase 1data/methodology.json → restart at Phase 2data/findings.json → restart at Phase 3, cycle 1data/findings.json but no summary.md → restart at Phase 3, evaluate current cyclesummary.md → Gate 1 reviewFor wider failure modes — API hiccups, Ollama restarts, Obsidian lock files, corrupted case JSON, stale review-feedback markers — see docs/recovery.md.
When sensitive: true is set in AGENTS.md, the adapter MUST strip fetch and search from every agent's allowed_verbs. The orchestrator then:
read-file, grep-files, list-files, query-vault){CASE_DIR}/research/npx claudepluginhub buriedsignals/spotlight --plugin spotlightOrchestrates OSINT investigations: preflight checks search tools and plugins, delegates research to agents, enforces user approval gates, archives findings to Obsidian vaults or directories.
Executes multi-agent research pipeline on any topic with Scout, Investigators, Deep Diver, Verifier, Synthesizer, and Critic reviews to produce verified, sourced reports.
Runs structured multi-step web research with source synthesis, citations, skeptical evaluation, and confidence/gap analysis. Supports native and dense/frontier modes.