본문으로 건너뛰기
P

dsh-sherlock

perrylink/dsh-sherlock

Public-username checks over a pinned 481-site Sherlock manifest; six states, random negative-sample verification for claimed results, default core 41, all capped at 120, NSFW off by default.

설치

dsh plugin --profile web add github:perrylink/dsh-sherlock

README

dsh-sherlock

CI

A temporal evidence workbench for DeepSeek Harness (DSH), with the earlier username-check tools kept as legacy.

It does not build or host a website. It does not search for people. It takes public URLs (and optional DSH search results), freezes local snapshots, separates the different clocks on a date, reconstructs a reviewable timeline, and reports conflicts, gaps, and coverage. It never issues a true/false verdict.

The name is retained for continuity. The product direction is temporal evidence, not username enumeration.

What it does

chrono_case → chrono_ingest / chrono_feed / chrono_gdelt / chrono_archive → chrono_assert → chrono_analyze → chrono_report

  • chrono_case creates/opens a local case.
  • chrono_ingest fetches 1–10 public URLs, stores text snapshots and SHA-256, and extracts declared dates.
  • chrono_assert records an event and its raw date assertions with a role (event, announcement, effective, publication, update, correction, retraction, access, deadline, period).
  • chrono_analyze runs deterministic conflict/evidence/timeline/gap/coverage analysis.
  • Every source/query is recorded in queries.jsonl; the report has a query log and TEG per time value. The robots gate and per-host delay apply to URL ingestion.
  • chrono_report writes a self-contained report.html, report.md, timeline.csv, sources.csv, and report.manifest.json; presentFiles recommends four.
  • The chrono-investigation skill carries the method: five clocks, T-S-C-E, conflict handling, uncertainty language.

Five clocks (never collapsed into one "date")

AxisMeaning
E Eventwhen the asserted event happened or took effect
P Publicationwhen the assertion was first made public
F First seenearliest proof that anyone could have seen it (archive)
O Observedwhen this workbench fetched it
M Modifiedwhen the source says it was edited/retracted

The precedence axioms E ≤ P ≤ F ≤ O, P ≤ M, E ≤ M are checked; a violation is a temporal_anomaly, not a conclusion.

T-S-C-E evidence vector

Every event/claim carries:

  • T time precision/timezone/role,
  • S source traceability,
  • C independent corroboration,
  • E snapshot/span/hash reproducibility.

The report shows the vector and a band (low/medium/high), not a single "credibility percentage". A single source or a syndicated copy can never be high.

Date conflict classes

hard_time (same role, comparable precision, disjoint intervals), role_mismatch, precision_mismatch, timezone_ambiguity, sequence, version, dependence. The report says what would resolve a conflict; it does not pick a "true" date.

Coverage statement

A negative conclusion requires a coverage statement: what was queried, where, in which window/language/domain scope, when, how many results, and what was unreachable. not checked, checked and not found, unreachable, and insufficient evidence are distinct.

Quick start

dsh plugin --profile <profile> add dsh-sherlock

Ask DSH:

Create a temporal case for this question: "When did Acme announce the factory closure, and why do the two sources disagree?"
I have these URLs: ...
Use chrono_case, chrono_ingest, chrono_assert, chrono_analyze, and chrono_report.
Do not decide which source is true; show the date roles, conflicts, gaps, and what would resolve them.

Or call the tools directly in PTC:

const c = await tools.chrono_case({
  action: 'create',
  title: 'Acme closure timeline',
  question: 'When did Acme announce the closure?',
  purpose: 'internal',
  subject_type: 'organization',
  subject_name: 'Acme'
})
await tools.chrono_ingest({ case_id: c.caseId, urls: ['https://example.com/notice'] })
// Read the returned source id, then record the raw date text. Do not calculate the date.
await tools.chrono_assert({
  case_id: c.caseId,
  source_id: '<source-id>',
  event_label: 'Acme announced the closure',
  event_category: 'corporate',
  dates: [{ raw_text: '2024年3月15日', role: 'announcement' }]
})
await tools.chrono_analyze({ case_id: c.caseId, action: 'check' })
await tools.chrono_report({ case_id: c.caseId, audience: 'internal' })

Run npm run benchmark:temporal for the local temporal benchmark (no network).

Reports support redaction: internal | client | public | legal; PII in labels, claims, titles and query logs is redacted, and public only renders high/medium-band rows. chrono_index lists/filters local cases without a hosted database.

The report tool writes local files, including a self-contained report.html timeline/conflict board. The model should call DSH present with the four presentFiles (report.html, report.md, timeline.csv, report.manifest.json); sources.csv remains in the case. The plugin does not upload them. A human can use /chrono list, /chrono status <caseId>, or /chrono report <caseId>.

Tools

ToolPurpose
chrono_casecreate/open/list a local case
chrono_searchoptional discovery via DSH search; returns URLs, not evidence
chrono_plandeterministic query plan (subject/alias/event/windows)
chrono_ingestfreeze public URL snapshots + metadata
chrono_indexlist/search local cases
chrono_feedRSS/Atom entries + optional ingest
chrono_gdeltGDELT DOC 2.0 news discovery + optional ingest
chrono_archiveWayback CDX captures; optional/fallback-aware
chrono_collectup to 50 URLs; DSH job or foreground fallback
chrono_watchdurable local watch via DSH schedule
chrono_diffdeterministic diff against a prior report
chrono_verifyre-fetch a source and record hash/status drift
chrono_claimrecord a claim/statement in the case
chrono_reviewhuman review/resolution of a conflict
chrono_assertrecord events and raw date assertions
chrono_analyzeconflicts, evidence vectors, timeline, gaps, coverage
chrono_reportvisual report.html + Markdown/CSV + manifest hashes
sherlock_checklegacy username check; kept for existing users
sherlock_siteslegacy site list

The sherlock-osint skill is retained for why it is now legacy. The primary workflow is chrono-investigation.

Local case store

Default root: .dsh-sherlock/chrono under the host working directory.

cases/<caseId>/
  case.json
  sources.jsonl
  watch.json
  events.jsonl
  dates.jsonl
  snapshots/<snapshotId>.txt
  conflicts.json
  gaps.json
  coverage.json
  reports/<reportId>/
    report.md
    timeline.csv
    sources.csv
    report.manifest.json

No website, server, account, or external database is created. Case IDs are generated by the plugin; the model cannot pass a filesystem path.

Configuration

- insert:
    - id: dsh-sherlock
      name: dsh-sherlock
      config:
        chronoRoot: .dsh-sherlock/chrono
        chronoMaxSources: 50
        chronoMaxBytes: 2097152
        chronoTimeoutMs: 15000
        chronoPerHostDelayMs: 250
        chronoHonorRobots: true
        # legacy username tools
        defaultScope: core
        maxSites: 120
        concurrency: 10
        perHostDelayMs: 350
        timeoutMs: 10000
        toolTimeoutMs: 180000
        maxResponseBytes: 524288
        maxVerify: 30
        cacheTtlMs: 600000
        includeNsfw: false
        honorExclusions: true
        allowPrivateHosts: false

The temporal tools reject private/loopback hosts. allowPrivateHosts belongs to the legacy test-only path; do not enable it in a profile.

Safety and boundaries

  • Public sources only; no login, paywall, CAPTCHA, WAF bypass, or credential use.
  • No self-hosted site, SaaS, crawler network, or bulk collection.
  • No identity/attribution conclusion; no people search, doxxing, or high-impact decisions.
  • No raw HTML/full article text in the report; short quotes + links + hashes only.
  • A hash is an integrity check, not a trusted timestamp or legal opinion.
  • The workbench does not decide whether a claim is true; it reports what the collected evidence supports, what conflicts, and what remains unknown.

Legacy username tools

sherlock_check and sherlock_sites still operate on the pinned Sherlock-format manifest in data/sites.json, with the original six states (claimed, available, unknown, blocked, illegal, unreliable), random negative controls, and a 120-site cap. They are deprecated as a product direction; see docs/LEGACY-USERNAME.md for the old behavior and data notice.

The upstream data is MIT-licensed; see data/SHERLOCK-LICENSE and NOTICE. The plugin code is Apache-2.0.

Development

Requires Node 24.9+.

npm ci
npm run typecheck
npm run lint
npm test
npm run check
npm run gate

npm run gate runs data validation, TypeScript checkJs, oxlint, the Node test suite, and npm pack --dry-run. The real DSH schema validator can be used with:

DSH_TOOLS_PATH=/path/to/dsh-tools/lib/index.js npm test

Documentation

License

Apache-2.0 for the plugin code; MIT for the legacy Sherlock-derived data. See LICENSE, NOTICE, data/SHERLOCK-LICENSE.

관련 플러그인