deepseek-harness/packages
imccyu 3e9527278a fix(tool-cordis): gate façade services on inject, and make tools.get read-only
Two review findings (#220) on the sandbox context façade:

- Undeclared services were reachable: the façade resolved any live global via
  ctx.get(name), so ctx.bash worked without inject: ['bash']. A cross-mount
  consumer could then depend on a provider cordis never saw — unmounting the
  provider would neither park the consumer nor unwind its registered tools,
  leaving a model-visible tool that fails only at execution. The façade now
  reads ctx.fiber.inject and refuses any service the mount did not declare
  (with a teaching error naming the inject fix), so the dependency is always
  visible to cordis and its activation/unload semantics bind.

- ctx.tools.get returned the live ToolDefinition, including execute — mount
  code could call another tool directly and bypass ToolRegistry.execute and
  its pre/post-execute hooks and accounting. get now returns the same
  read-only name/description/parameters view as schemas(), never an invocable.

Adds inject-gate and schema-view regression cases to sandbox-context.spec.ts
(undeclared property/get denied, declared allowed, the cross-mount zombie-tool
scenario refused at call time, get exposes no execute). Package stays at
per-file 100% coverage. RFC, mount description, and tool-catalog updated.
2026-07-09 13:57:03 +08:00
..
bash Merge remote-tracking branch 'origin/master' into timeout-design 2026-07-09 11:52:18 +08:00
code-runtime docs: state advisory typing in the worker row (review) 2026-07-09 00:38:21 +08:00
compact Merge remote-tracking branch 'origin/master' into worktree-export-jsdoc-gate 2026-07-07 09:34:12 +08:00
cordis fix(tool-cordis): gate façade services on inject, and make tools.get read-only 2026-07-09 13:57:03 +08:00
core feat(cordis): @deepseek-ai/dsh-tool-cordis — inspect/mount/unmount over the live runtime 2026-07-09 13:57:03 +08:00
fs Merge origin/master into timeout-design 2026-07-08 11:18:27 +08:00
guard fix review finding: cap the detailed reminder's argument payload 2026-07-08 14:40:08 +08:00
hooks test: drain the detached SubagentStart continuation before the bridge spec ends 2026-07-07 09:37:50 +08:00
llm Gate JSDoc completeness on every package export 2026-07-06 22:09:30 +08:00
session-persistence Merge remote-tracking branch 'origin/master' into worktree-node-22-18-compat 2026-07-07 21:33:40 +08:00
subagent Merge remote-tracking branch 'origin/master' into structured-output-subagent-seam 2026-07-07 21:40:07 +08:00
support test(acp-snapshot): replace the authored-implies-override guard with an explicit overridden flag 2026-07-08 14:24:20 +08:00
timeout chore(timeout-policy): drop now-unused schemastery dependency 2026-07-08 15:10:15 +08:00
todo Merge remote-tracking branch 'origin/master' into simpl-b1-fold-ui-stdio 2026-07-04 20:38:38 +08:00
ui Merge branch 'master' into worktree-node-22-18-compat 2026-07-07 22:46:02 +08:00
util test: make the timeout-wins race deterministic under fake timers 2026-07-06 19:55:46 +08:00
web feat(tool-web): declare web tool timeout budgets via config 2026-07-08 14:40:14 +08:00
AGENTS.md docs(AGENTS): rewrite the root standing orders to the 1,500-word budget 2026-07-04 14:22:47 +08:00
CLAUDE.md Document the codebase thoroughly and tighten type safety 2026-06-11 13:01:00 +08:00
README.md chore: register the cordis group across repo gates and docs 2026-07-09 13:57:03 +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
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 (the ACP bridge) + the app packages 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).