DSH Plugins Marketplace

DSH Plugins

Plugins

/

Workflow & Automation

/

dsh-first-hop

b

dsh-first-hop

Identified

Your agent wakes on evidence, not on a clock. A community plugin for DeepSeek Harness: watches the streams your harness already carries and decides - hold, flag, counsel, or wake. Local judge, shadow

dsh-first-hop

Your agent wakes on evidence. Not on a clock.

A community plugin for DeepSeek Harness. It watches the streams your harness already carries and, at each boundary, decides one of four things — hold, flag, counsel, or wake.

MIT · runs entirely local · shadow by default · bring your own 9B.

"Input reaches the driver through one inbox. Some messages wake it immediately; injected context waits in the inbox until another message does." — DeepSeek Harness architecture documentation, docs/architecture.md

Until that other message arrives, nobody is home. The chain of who-wakes-your-agent ends at a clock, a webhook, or you. dsh ships a scheduler that wakes on timers; this plugin is its evidence-fired sibling.

Status: v0.1.0, pre-release. The constitution below is implemented and tested. The wake and counsel verbs are gated behind a runtime capability check and are not yet verified against a pinned harness build — see Verify before live. Run it in shadow.


Install

npm i dsh-first-hop
# cordis.yml
plugins:
  dsh-first-hop:
    judge:
      tier: floor            # floor | local | mock

Then opt in. Nothing happens until you do:

echo shadow > ~/.dsh/first-hop/first-hop.state

Read the tape for a week before you consider live.

The switch

~/.dsh/first-hop/first-hop.state   →   off | shadow | live

The state is a file only you write. No code path in this package writes it — not to create a default, not to recover from a bad value, not at any version. An absent or unrecognized file reads as off.

PositionWhat happens
off (also: no file)Nothing. No file created, no percept read, no judge consulted, no pill written. Off means absent.
shadowWatches, judges, and records everything — and consumes no verdict. This is where trust is earned.
liveAdditionally resolves verdicts into harness acts, within the limits below.

Three files appear beside the switch once you are awake:

  • spool.tsv — every percept, in lane-contract v0.1 frames
  • first-hop.tape.jsonl — every judgment, including every hold
  • first-hop.heartbeat.json — the pill; older than three beats means stalled

None of them ever leaves your machine.

The two tiers

Tier 0 — the floor. Deterministic rules that need no model and no tokens: CI state, test results, non-zero exits. Ships enabled. It is also the null — the baseline the model tier has to beat before anyone should run it.

Tier 1 — the 9B judge. For what no rule can name. Any OpenAI-compatible local endpoint: llama.cpp server, Ollama, LM Studio, vLLM. One bounded request per boundary, strict-JSON answer, closed vocabulary.

plugins:
  dsh-first-hop:
    judge:
      tier: local
      endpoint: http://127.0.0.1:8080/v1
      model: qwen3-9b-instruct-q5_k_m
    budgets:
      wake: 2                # per condition class, per hour
      flag: 6
    verbs:
      wake: true
      counsel: false         # off by default, deliberately
    floor:
      builtins: true
      rules:
        - id: deploy-failed
          pattern: 'deploy (failed|rejected)'
          flags: i
          action: wake
          reason: a deployment reported failure
      retired: []

Every deployment-varying value is a validated config field, and a malformed composition fails at load rather than at the first boundary. The full surface is src/config.ts.

What this is not

  • Not the kernel. No KV residency, no token-grain decode-on-delta, no microsecond aborts. Judgment here is boundary-batched at commit grain: evidence-fired, but not resident. It is an analog of that mechanism, and no number it produces should be quoted as if it were that mechanism's.
  • The judge is prompted, not tuned. A stock 9B can flood or go deaf. That is precisely why shadow is the default, budgets are constitutional, and the floor is co-equal. The failure modes are designed for, not denied.
  • Not an actuator. Live mode has two verbs that reach a model, both landing inside your own session. It cannot touch the world, hold credentials, or approve anything.
  • Not a telemetry client. No server, no account, no beacon. The tape stays on your disk.
  • The judge reads everything. To judge your sessions it must see them — every message, every tool result. That is exactly why the endpoint should be yours. Point it at a hosted API and you have handed your sessions to a vendor and reintroduced the request boundary this plugin exists to close. It will let you.

The nine laws

Off is inert · holds are on the tape · see it once · budgets at condition grain · self-echo suppression · shadow before live · percepts are never dropped · model-visible ⟺ logged · lane text is data, never instructions.

Each one is a test, a file permission, or a structural property — with the file named. See LAWS.md.

L9 is the one the other eight exist to protect. The streams this plugin watches are attacker-reachable, so nothing a judge returns is trusted: every verdict is re-derived into a closed vocabulary (four literal actions, a re-slugged condition id, a control-stripped and capped reason), and every other field a model invents is dropped. A poisoned log can argue for a wake; it cannot become one.

Verify before live

wake and counsel construct a harness message and hand it to the agent's whenIdle → runMaintenance → followup sequence. Those three methods were read from packages/core/agent/src/runtime-types.ts, but the message shape this package builds has not been verified against a pinned harness build, so dispatch() performs a runtime capability check and refuses cleanly rather than guessing. Until you have verified it against your own pin:

  • run in shadow — everything is recorded, nothing is consumed
  • see the FIXME(pin) in src/index.ts for the one function to check

This is the honest state of a pre-release plugin against a pre-release harness (SESSION_FORMAT_VERSION: 0, compatibility breaks expected). Pin your harness, and CI against the pin.

Architecture

src/core/      the constitution — pure Node, zero harness imports
  state.ts       the control file (the reader is total; nothing writes it)
  spool.ts       lane-contract v0.1 frames; the buffer that makes L1 true
  tape.ts        append-only JSONL, holds included
  ledger.ts      see-it-once + budgets at condition grain
  verdict.ts     the closed vocabulary — where L9 is enforced
  judge/         floor (deterministic) · local (9B) · mock (for CI)
src/plugin/    the harness-facing edge
  tap.ts         events → percepts, structurally typed, pure
  verbs.ts       verdict → act, behind a runtime capability check
  pill.ts        the heartbeat

src/core imports nothing from the harness, which is why the whole constitution is testable in CI with no harness, no key, and no GPU — and why another venue could reuse it to be judged by the same rules over a different stream.

Note on dependencies: this package deliberately does not depend on @deepseek-ai/dsh-session. That package is published but currently uninstallable — it depends on @deepseek-ai/dsh-type-meta, which is not on the registry. Harness event shapes are therefore read structurally, which is also the looser coupling.

Development

pnpm install
pnpm run typecheck
pnpm test          # 48 tests, no GPU, no key, no harness
pnpm run build

Roadmap

  • v0.2 — verified live dispatch against a pinned harness; the first-hop CLI (status, tape, retire, resolve).
  • v0.3 — first-hop bench: replay your own session logs, retro-label the boundaries, and race the judge against the best swept polling policy at every token budget, both grains printed. If the judge does not dominate your polling frontier, the bench says so, and the advice is: keep the floor, skip the judge. A tool that cannot lose cannot be trusted to win.
  • v0.4 — more lanes (filesystem, CI); the lane-contract socket, so a native resident kernel can take the judge's chair without the plugin changing.

Lineage

The first hop of the FUSOR architecture, in portable form. FUSOR is a substrate for minds that do not take turns; this is the smallest useful piece of that idea that runs on someone else's harness, on your hardware, under your switch.

License

MIT

Comments

Loading…

Similar plugins

dsh-sentinel

by fuhefei

Condition-driven wakeup for DeepSeek Harness: durable file/command/http/process/webhook watches that wake the agent, with dock, sidebar branch, and a global dashboard.

Workflow & AutomationManifest valid

★ 18

↓ 128/wk

BSD-3-Clause

TypeScript

Oct 7, 2026

dsh plugin --profile web add dsh-sentinel

by shengsheng90

Native local Taskboard plugin for DeepSeek Harness. SQLite-backed projects, Agent claim/review, and a native Web UI — no iframe, no second chat runtime.

Workflow & AutomationManifest valid

★ 331

↓ 376/wk

Apache-2.0

TypeScript

Sep 30, 2026

dsh plugin --profile web add @shengsheng/dsh-taskboard

by Apageoflove

Local-first experiment and evaluation workbench plugin for DeepSeek Harness (DSH).

Development & InfrastructureTerminal & ClientsManifest valid

★ 3

↓ 5/wk

MIT

JavaScript

Sep 18, 2026

dsh plugin --profile web add dsh-arena

by Leitarkkk

DeepSeek Harness plugin that auto-nudges agents to consult docs or web search when local trial-and-error becomes costly. DeepSeek Harness 插件:当本地试错成本升高时,自动注入检索提示,引导 Agent 查阅文档或联网搜索。

Development & InfrastructureManifest valid

★ 4

↓ 109/wk

MIT

JavaScript

Aug 28, 2026

dsh plugin --profile web add dsh-research-nudge

by kingcheng12

DeepSeek Harness plugin that surfaces concurrent workspace changes before an agent continues.

Development & InfrastructureManifest valid

★ 0

MIT

TypeScript

Aug 31, 2026

dsh plugin --profile web add dsh-workspace-change-awareness

by guhanfei-ai

Local-first self-observability for DeepSeek Harness — events, personal metrics and reality feedback.

Development & InfrastructureTerminal & ClientsManifest valid

★ 0

MIT

JavaScript

Sep 17, 2026

dsh plugin --profile web add dsh-introspect