Files
deepseek-harness/packages/AGENTS.md
Tianyi Cui ecb8aa5b8e Add a gated Known Limitations and Deferred Work section to every package README
Every packages/*/* README now carries a canonical '## Known Limitations and
Deferred Work' section: condensed, evidence-backed bullets for consumer-visible
gaps (unimplemented features, platform caveats, MVP cuts) and consciously
postponed work (TODO/FIXME/XXX markers, RFC deferrals still open). The ten
pre-existing ad-hoc variants ('What is NOT here (TODO)', 'Deferred',
'Limitations (MVP)', 'Known limitations (tracked TODOs)', ...) are normalized
into the canonical heading.

A new doc-sync gate, scripts/verify-readme-limitations.ts, enforces the shape:
exactly one limitations-like heading per package README, byte-equal to the
canonical h2, with at least one bullet; near-miss headings fail so variants
cannot creep back. Packages with genuinely nothing to declare (dsh-brand,
dsh-timeout, dsh-subagent-mock, dsh-app-boot) are whitelisted in the script and
must NOT carry the section; whitelist entries are validated against the scanned
package set so a rename fails loud.

Wired into the doc-sync chain (package.json) and the run-gates doc-sync leaf
set; the standing rule lands in packages/AGENTS.md and the adding-a-package
cookbook; decision record in
docs/rfc/implemented/process/2026-07-10-readme-known-limitations-gate.md
(RFC index regenerated).

Also fixes two stale '(deferred)' markers claiming dsh-compact-basic is
unimplemented (the dsh-compact seam README's package table and the seam's
module doc comment).
2026-07-12 01:46:34 +08:00

3.3 KiB

AGENTS.md — Harness Packages

This directory contains all @deepseek-ai/dsh-* harness packages. Repo-wide conventions (effects, declaration merging, waterfall semantics, ESM, testing policy) are in the root AGENTS.md § Conventions; the points below are packages-specific.

  • Plugin export shape — namespace OR default, never both. A service package exports the service class as export default (the Loader instantiates it). A function/namespace plugin exports name / inject / Config / apply as separate named exports and must NOT add export default — the cordis Loader's unwrapExports does exports.default ?? exports, so a stray default export collapses the module to the bare apply function and silently discards the inject/name/Config namespace, leaving the plugin with no injected services (it then throws cannot get property … without inject at load). See docs/postmortem/0001.
  • Read an optional (non-injected) service via ctx.get(name), not ctx.<name>. For a service a plugin reads opportunistically but deliberately leaves out of static inject (e.g. AgentLoop reading sessionPersistence), the ctx.<name> property proxy resolves by an ancestor-only fiber walk that throws when the call arrives through a foreign traceable shadow (the service lives on a sibling fiber). ctx.get(name) is the topology-independent global-store lookup, strict by default (an inactive/absent backend reads as undefined — prefer it over the ctx.get(name, false) overload, which also skips the active-state check). Services that ARE in static inject resolve fine via ctx.<name>. See docs/postmortem/0001.
  • A plugin shipped via cordis.yml needs at least one test through the REAL Loader/export path — hand-built ctx.plugin({...}) mounts bypass unwrapExports and cannot catch a broken export shape. Full testing policy (tiers, with-key generosity, real-entry-path guards): docs/testing.md.

Naming notes:

  • A service src/index.ts exports the service class as export default + all public types; a function/namespace plugin src/index.ts exports name/inject/Config/apply as named exports and NO default (the export-shape rule above).
  • src/types.ts contains only types — no runtime code.
  • Tests live at package level under tests/, not src/__tests__/.
  • A package's README and JSDoc are part of the change: altered behavior (config keys, defaults, error codes, wire fields) updates them in the same commit. doc-sync gates what it can; prose accuracy stays on the author (the documentation standard).
  • Every package README carries a ## Known Limitations and Deferred Work section — condensed bullets for consumer-visible gaps and consciously postponed work; verify-readme-limitations (in doc-sync) gates it. A package with genuinely nothing to declare is instead whitelisted in scripts/verify-readme-limitations.ts and must not carry the section (rationale).

Read the per-package README.md for package-specific details: service API, events, extension points, known limitations.