Files
deepseek-harness/packages
Yichen Jiang 43d60286e3 fix(tasks): an aborted wait must not leave a settled task notice-suppressed (review finding)
Two windows where settle() could read a live waiter count, mark the
task reported (suppressing the completion notice), and then watch that
waiter reject with 'wait aborted' delivering nothing — leaving the
owning session with no terminal notification at all:

- abort and settlement in the same tick, settle continuation ordered
  first: the waiter now un-counts itself SYNCHRONOUSLY inside onAbort
  (the finally decrement alone lands a microtask too late), so the
  settle path sees no live waiter and the notice fires;
- abort landing after settlement but before the wait's resolve
  microtask: the wait now resolves and DELIVERS the terminal snapshot
  it owes instead of rejecting (settlement suppressed the notice on
  this waiter's behalf).

Both windows pinned by deterministic tests that fail on the previous
implementation; wait()'s abort contract updated in JSDoc/README/RFC.
2026-07-09 23:08:26 +08:00
..

Packages

Harness packages, all under the @deepseek-ai/dsh-* scope. Each package is a Cordis plugin (microkernel-style): it exports either a default Service subclass or a functional plugin, declares its ctx key/events through declaration merging, and exposes extension points through ctx.effect(), ctx.on(), and ctx.waterfall(). Authoring conventions: AGENTS.md (subtree) and the root AGENTS.md § Conventions.

Hierarchy

Packages are grouped by modular role at packages/<group>/<pkg>/. The group directory is a pure container (no package.json of its own); the package name stays @deepseek-ai/dsh-<pkg> regardless of group. Each group README is the canonical per-package map — package roles, ctx keys, and the product-vs-support split live there, next to the code.

Group Role Release expectation
core/ Product API spine: session, system-prompt, tools, agent, and the concrete loop Product — stable surface
llm/ LLM capability family: the abstract service + provider adapters Product — stable surface
bash/ Bash capability family: the executor seam, a local impl, and the model-facing tool Product — stable surface
code-runtime/ Code-execution capability family: the abstract runtime seam for model-written programs + a worker-thread backend Product — stable surface
fs/ Filesystem capability family: the abstract seam, a local impl, and the model-facing file tools Product — stable surface
compact/ Compaction capability family: the abstract seam + a basic backend (tool deferred) Product — stable surface
subagent/ Subagent capability family: the provider-registry seam and the model-facing delegation tool Product — stable surface
tasks/ Background task family: the ctx.tasks registry + the generic task_* control tools Product — stable surface
web/ Web capability family: the abstract seam, search/fetch provider impls, and the model-facing web tools Product — stable surface
timeout/ Tool-call timeout policy: the tools/execute deadline enforcer Product — stable surface
todo/ Todo/planning family: the model-facing todo_write tool Product — stable surface
guard/ Loop-hygiene guards: advisory repeat-call reminders Product — stable surface
cordis/ Self-referential runtime toolset: inspect the live runtime's plugins and services, mount/unmount model-written plugins (design) Product — stable surface
hooks/ Hook bridges + the shared Claude Code / Codex wire-protocol library Product — stable surface
session-persistence/ Persistence capability family: the seam + JSONL/SQLite backends Product — stable surface
ui/ Editor/client integration surfaces: ACP bridge, app packages, user-interaction seam, ask-user tool Product — stable surface
support/ Dev/test/example infrastructure (invariants, replay adapter, subagent mock) Support — lower compatibility expectations
util/ Low-level zero-dependency utilities shared across groups (the Branded<B> primitive) Support — small, stable, harness-dep-free

The split is the point: a package's group says whether it is part of the product API or support/test/example infrastructure, so release and removal decisions do not treat every package as an equal public contract. New packages join an existing group; adding a new top-level group is a deliberate act (extend the group READMEs and this table).

Dependencies

The inter-package dependency graph is generated: docs/module-graph.md (pnpm run gen-module-graph, freshness-gated in CI).

The rule it must obey: extension plugins depend on interfaces, never on the concrete loop. dsh-agent-loop is swappable — UI/hook/tool plugins keep working against the dsh-agent vocabulary if the loop is replaced. The sanctioned exception is a composition/bundle package like dsh-agent-core, whose whole job is to assemble the concrete spine: it depends on dsh-agent-loop (and the other concrete spine plugins) on purpose. The rule constrains plugins that EXTEND the system, not the bundle that COMPOSES it. A swappable capability splits into interface / implementation / consumer packages (the bash trio is the template — see capability seams).

Each package has its own README.md with purpose, service API, events, extension points, and deliberate non-goals (TODOs).