npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-agents-playbook

v0.8.0

Published

DeepSeek Harness plugin for Agent-Playbook: multi-agent claims, isolated git worktrees, and enforced acceptance checks. "Done" is an exit code, not a claim.

Readme

dsh-agents-playbook

A DeepSeek Harness plugin for Agent-Playbook.

The engine's whole thesis is one sentence: "done" is an exit code, not a claim. A task's acceptance_checks are shell commands, and recording it done re-runs them and refuses if any fail. This plugin brings that loop into the harness — with multi-agent attribution and isolated git worktrees.


Why a plugin, and what it deliberately does not do

| Owns | System | |---|---| | Truth — backlog, claims, journals, acceptance checks, worktrees | Agent-Playbook (the engine) | | Convenience — agent identity, context injection, model-facing tools | this plugin (the harness) |

The plugin never re-implements a gate. Every action translates into a pb invocation. If something cannot be expressed as a pb call, the engine does not support it yet — and inventing a second opinion about "done" is exactly the failure this design refuses.

It also shells out rather than importing the engine. That is not laziness: every engine command reports refusal with process.exit(), so an in-process call would terminate the harness instead of returning an error. As a subprocess, the exit code remains the contract.


What it gives you

1. Multi-agent writes stay attributable

Fan-out is the point, and it is where naive setups lose data. The plugin stamps every engine call with a real identity:

| Variable | Meaning | |---|---| | PB_AGENT_ID | who is writing (defaults to the harness session id) | | PB_SESSION_ID | which harness session it came from | | PB_PARENT_AGENT_ID | the spawning agent, for sub-agents | | PB_AGENT_CHAIN | the full delegation path (root,sub,grand) | | PB_CLAIM_TOKEN | proof of entitlement to the task this agent holds | | PB_RUNTIME | dsh, so records show which host wrote them |

So a sub-agent writes as itself and is recorded as itself, while the engine can still verify it was entitled to touch its ancestor's claim. A refused write is flagged ownership: unproven — never silently dropped, never silently allowed.

Under the hood the engine serializes every state write through one lock and an atomic replace, and stamps each journal row with a monotonic seq. "Who wrote first, who wrote last, and on whose behalf" is a recorded fact, not an inference from colliding timestamps.

2. Isolated worktrees, gated merges

worker actions drive a real git worktree per task:

create   → open a slot (atomic: one live slot per task, no orphan worktrees)
status   → ahead / behind / uncommitted / head
exec     → run a command INSIDE the worktree
verify   → run the task's acceptance_checks INSIDE the worktree
merge    → gated by merge-ready; refuses unless the branch actually carries verified work
remove   → tear the slot down

The merge gate reads the branch, not just the journal: a worktree that is missing, dirty, or has zero commits ahead of its base cannot be merged, and a verification that has gone stale is reported rather than trusted.

3. The constitution survives compaction

Before each agent step the plugin stages a short context block on the agent's inbox:

[agent-playbook]
playbook: my-project v0.3.6
loop: loop-7 — finish the worktree lifecycle
north star: Make "done" mean a verified exit code, not a claim.
backlog: 2 todo · 1 in_progress · 0 blocked · 4 done
in progress: T1 (alice)
task in hand: [T1] Do the thing
done means these exit 0:
  $ npm test
  $ node scripts/pb.mjs validate
Rule: "done" is an exit code, not a claim. Record with `pb record` — it re-runs the checks and refuses on failure.

The North Star, the active loop, the task in hand and its checks are re-injected every step, so a long session or a compaction cannot lose the plot. When the backlog has nothing actionable the block is suppressed (quietWhenIdle) rather than burning tokens.

4. The playbook's own skills are loadable

The project's skills/<id>/SKILL.md files are registered as harness skills, so its procedures load the same way the harness's built-in ones do — including mode-local skills, because the ENGINE's own resolution decides which are active (nothing is re-implemented in the plugin).

They are namespaced playbook-<id>: a harness skill is invoked by slot (/name) and a playbook skill by path, so a bare id could shadow an unrelated harness skill. The catalog is discovered live on each list, so a skill added to skills/index.yaml appears without a restart; bodies load on demand rather than at discovery.

A loaded body is prefixed with its routing, because a playbook skill that says "follow the process" is useless without knowing which process file the engine's skills-first routing keys on:

# Playbook skill: run-task
This skill belongs to the workspace playbook. Operate the project through it:
- skill file: skills/run-task/SKILL.md
- canonical process: processes/run-task.yaml — follow it step by step
- record work with the `playbook` tool; "done" is an acceptance check exiting 0, not a claim

Install

The plugin carries the engine, so this is one install — no separate engine checkout and no version to keep in step by hand.

dsh plugin --profile <profile> add dsh-agents-playbook

That is the whole install. It installs the package AND enables it: dsh plugin forwards to pnpm inside the profile directory, then reconciles dsh.profile.bundles — a dependency whose package declares dsh.bundle.patch is appended to the layer stack automatically. There is no bundle list to edit by hand.

Verified end to end — after that one command, $DSH_HOME/profiles/<profile>/package.json contains both

"dependencies": { "dsh-agents-playbook": "^0.6.2" },
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "…", "dsh-agents-playbook"] } }

and dsh --profile <profile> --dump-config composes - id: agent-playbook.

Prerequisite: pnpm

dsh plugin is a pnpm forwarder, so pnpm must be on PATH:

npm install -g pnpm        # or, if you have corepack: corepack enable pnpm

Without it the command fails with dsh: pnpm not found on PATH (exit 127).

What does NOT work: plain npm install

npm install dsh-agents-playbook does not enable the plugin. It installs a package into whatever directory you happen to be in, and the harness only reads $DSH_HOME/profiles/<name>/package.json — so the plugin lands where nothing looks for it and nothing appears to happen. That is the confusing "installed but DSH wants more steps" state.

If you would rather manage the dependency yourself, the manual equivalent is to install it into the profile directory and add it to the bundle list — the package declares dsh.bundle.patch, so the name alone is the mount:

{ "dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "dsh-agents-playbook"] } } }

Two things that look like problems but are not

  • pnpm peers check reports five missing peers. It inspects only the profile's own node_modules. The harness resolves its packages through $DSH_HOME/profiles/node_modules — a directory of junctions the launcher maintains, one level above the profile — so @deepseek-ai/cordis, dsh-agent, dsh-llm, dsh-tools and schemastery all resolve at runtime.
  • pnpm edits pnpm-workspace.yaml. Installing a package published minutes earlier makes pnpm record a minimumReleaseAgeExclude entry. That is its supply-chain guard recording a deliberate exception, not an error.

After installing

  1. Reload the session. The profile is composed at boot (patchReload is live for the web profile and startup for headless), so a profile that gained a package wants a restart.
  2. Give the workspace a playbook. The plugin is deliberately dormant until it finds one.

Then scaffold one for the workspace you want to operate, from the agent itself:

playbook action=init

That writes .agents-playbook/ (engine + master + runtime files) into the session workspace, hydrates it with the engine's own init, and validates the result — all from the bundled engine. The workspace copy then takes over, so the playbook is self-hosting: it can scaffold further playbooks, and it does not depend on the plugin being installed to keep working.

If you already have a playbook (or want it somewhere else), point the plugin at it instead:

- insert:
    - id: agent-playbook
      name: 'dsh-agents-playbook'
      config:
        playbookPath: ''                  # '' → discover: nested locations, then ancestors
        playbookDir: '.agents-playbook'   # where action=init scaffolds
        injectContext: true
        quietWhenIdle: true
        maxContextChars: 4000
        commandTimeoutMs: 120000

There is no engine install requirement to load the plugin: it looks for a playbook in the well-known nested locations (.agents-playbook, .agent-playbook, .playbook, agent-playbook) and then walks up from the session workspace. The plural .agents-playbook is canonical; the singular .agent-playbook is a supported legacy alias for projects scaffolded before the spelling settled. It stays dormant when there is none — except that action=init always works, because that is what the bundled engine is for.

Which workspace it uses. The session's own directory, resolved from the harness workspace registry — never the server's process cwd. When no workspace can be resolved the plugin refuses (unknown workspace) rather than guessing, because guessing is how a playbook gets scaffolded into an unrelated project.

Which engine runs, and where

Two separate things, deliberately:

| | meaning | |---|---| | which engine | the workspace's own copy if it has one, else the bundled one | | which playbook | always a real workspace playbook — never the plugin's vendored copy |

A workspace playbook therefore wins over the bundle, and the bundle is never used as a target. That matters because the plugin now contains a playbook-shaped tree: a naive ancestor walk would "discover" it and operate on the wrong project.

Configuration

| Field | Default | Meaning | |---|---|---| | playbookPath | '' | Absolute path, or '' to discover (nested locations, then ancestors). | | playbookDir | .agents-playbook | Where action=init scaffolds a playbook. | | injectContext | true | Stage the constitution on the agent's inbox each step. | | quietWhenIdle | true | Stay silent when nothing is todo or in_progress. | | maxContextChars | 4000 | Character cap on the staged block. | | commandTimeoutMs | 120000 | Per-pb-invocation timeout. | | stopGate | true | Hold a turn open (once per claim) when it ends with an unresolved claim. |

The Stop gate

Everything else in this plugin asks the agent to verify. The gate is the one place the harness refuses: when a turn is about to end while this agent still holds a claim it never resolved, the turn is held open and the model is told which task to resolve and how.

It is built on agent/turn-stopping, which fires as a turn would otherwise close; a handler that calls agent.steer() keeps it open. That contract is pinned by scripts/test-dsh-stop-gate.mjs and was confirmed in a live session — the handler steered at fire 1 and the loop fired again for the same turn.

It is deliberately timid, because the harness documents the opposite failure: a handler that blocks unconditionally force-continues every step. So a given claim is reminded about at most once, the session caps its total, and the message says so. One extra step is a nudge; an unbounded one is a runaway. Set stopGate: false to make the loop advisory again.

The playbook tool

| Action | What it does | |---|---| | status | Orient: backlog counts, active loop, guardrail state, recent records. | | anchor | Re-inject the constitution (North Star + current cycle). | | next | Show the next claimable task and its checks, without claiming. | | claim | Claim it. Returns the claim token — pass it to a sub-agent so it can record on your behalf. | | task | One task's projection: status, holder, checks, gate quality, worker. | | check | Run that task's acceptance_checks on demand. | | record | Record an outcome. status=done re-runs the checks and refuses on failure. | | worker | Worktree lifecycle: create / status / exec / verify / merge / remove. | | init | Scaffold + hydrate a playbook from the bundled engine (works with none present). | | unlock | Report and (with force) clear a leaked lock. | | repair | Check or rebuild the state projection from the append-only journal. |

Delegating to a sub-agent

1. playbook action=claim                     → task + claim token
2. spawn the sub-agent with:
     PB_AGENT_ID=<sub>
     PB_PARENT_AGENT_ID=<you>
     PB_AGENT_CHAIN=<you>,<sub>
     PB_CLAIM_TOKEN=<token>
3. the sub-agent works in `worker create`/`verify` and records as ITSELF, proven
4. playbook action=worker workerAction=merge  → only after the gate opens

Development

npm run build:plugin          # bundle the engine into dsh-plugin/engine/ (generated, gitignored)
npm run pack:plugin           # build + `npm pack --dry-run` + manifest checks
node scripts/test-dsh-plugin-core.mjs    # host-independent logic (no harness needed)
DSH_PACKAGES=<path to @deepseek-ai> node scripts/test-dsh-plugin-index.mjs

core.mjs holds everything host-independent (identity, discovery, subprocess results, context rendering) so it is testable with plain node. index.js is the thin Cordis layer. The index suite loads the real module, registers the tool against a stub ctx, and executes it against a real playbook on disk; the bundle suite proves the shipped engine is complete, clean of this repository's state, and can bootstrap a workspace. Both skip cleanly when their prerequisites are absent, rather than failing for something the checkout cannot fix.

License

MIT