中文

# Development Guide ## Repository Structure ```text src/ index.ts # Plugin entry (pure re-export) service.ts # ZoteroService (Cordis service) library/ # Library panel subcomponent (ZoteroLibraryService, config schema) library-views.ts # Bidirectional mapping between the panel's wire views and domain requests library-write.ts # Panel write entry: rides the registered tool pipeline and its approval seam local/provider.ts # LocalApiProvider (Zotero Local API adapter) local/*-domain.ts # Domain pipelines (search, export, changes, browse, write, etc.) local/ # Helper modules: detail, retrieve, attachment-location, scope-directory, search-index, item-batch, etc. http-client.ts # HTTP transport layer (loopback fetch, streaming, and concurrency slot control) config.ts # Configuration schema and validation logic types.ts # Domain DTOs and type definitions contract.ts # Remote wire protocol surface and constants wire-schemas.ts # Wire boundary zod schemas shared by both codec arms creators.ts # Creator display formatting (shared across halves) media-types.ts # Media-type constants (shared across halves) diagnostics.ts # In-process diagnostics ring buffer, entry model, and sink status-codec.ts # Host-side status decoding (zod) abort.ts # The one spelling of the caller-cancellation error (harness TOOL_ABORTED) errors.ts # Error classes and error codes json.ts # Lossless JSON read helpers evidence-item.ts # Passage item projection definitions (shared across client/host) browse-rows.ts # Browse row classification (shared across client/host) changes-contract.ts # Shared wire descriptors for the changes projection projection-keys.ts # The zoteroStatus projection key and its type merge (shared across client/host) session-events.ts # The zotero/status session event and the status-to-wire view fold status-projection.ts # The zoteroStatus session projection unit (last-value fold) transport-bounds.ts # Response-body ceiling shared by the local and scholarly transports transport-diagnostics.ts # Transport-layer diagnostic line recording (requests, cancellation, degradation) constants.ts # Constant definitions concurrency.ts # Bounded concurrency controller job-runner.ts # ctx.jobs background-job adapter for the heavy tools evidence.ts # BM25 ranking algorithm search-text.ts # Search folding matching Zotero normalizeForSearch attachments.ts # Attachment selection and priority logic normalize.ts # Zotero response to domain DTO normalization presentation-meta.ts # Presentation projection for tool results refs.ts # Zotero ref syntax parsing and formatting ref-grammar.ts # Reference syntax validation patterns export-items.ts # BibTeX key grammar and field extraction export-mapping.ts # Reference and batch item mapping prompt.ts # Model-facing system prompt section command.ts # /zotero status command write-approval.ts # Two-tier write confirmation (approval policy and plan review card) write-auth.ts # Zotero local write key acquisition and persistence write-http.ts # Local write HTTP request handling write-item-rules.ts # Write field and update rules (shared by tools and write domain) shell-write-detector.ts # Shell command interception for direct Local API writes remote.ts # Web client Remote service typert.ts # Typert manifest settings-namespace.ts # Settings namespace constants tools/ # 23 local model tool definitions (8 read + 15 write) tools/degradable.ts # The degrade rule for write-tool plan previews (only unreachable or ambiguous targets) client/ # Browser client (configuration page, Sources panel, tool card views) tests/ # Unit and end-to-end test suites ``` ## Installation and Build ```sh npm install # Install dependencies (alongside deepseek-harness) npm test # Run unit tests and test specification checks npm run typecheck # Run type checking (Node, test, and client projects) npm run build # Compile all artifacts (tsc → lib/, esbuild → lib/client.js) npm run build:client # Build browser client artifact only npm run test:coverage # Check coverage gates npm run harness:check # Check upstream Harness version pin and artifact freshness npm run harness:pin -- # Update every dsh version face in package.json npm run verify:pack # Validate package tarball integrity npm run smoke # Production-stack smoke: every read tool against a live Zotero from a dsh profile npm run smoke:discovery # Packed tarball → throwaway profile → dsh web boot probe npm run release:branch # Cut the publishable release branch (manifest-driven) npm run release:check # Release gate: format, version pin, tests, types, coverage, build, pack npm run link:local-harness # Link @deepseek-ai/dsh-* dependencies to the sibling checkout npm run dev # Watch Node-half sources and compile incrementally npm run dev:client # Watch browser-half sources and bundle incrementally npm run lint:test # Run the test-lint guards only npm run test:watch # vitest watch mode npm run format # Format code with Prettier npm run format:check # Check code formatting ``` `prepare` (triggered by `npm install`) builds `lib/` from source; `prepublishOnly` runs `release:check` before a publish can go out. Note: This repository is typically developed as a sibling directory to `deepseek-harness`. Type declarations are resolved from upstream build artifacts via symlinks. If upstream code changes, run the upstream build first to synchronize declaration files. Published `@deepseek-ai/dsh-client-*` packages declare their third-party runtime dependencies in their own `devDependencies` (the shell supplies them when bundling) and reference `.module.css` files directly from `lib/`. This repository therefore mirrors those third-party dependencies in `devDependencies` and lists `@deepseek-ai/dsh-client-*` as inlined in `vitest.config.ts`, so the client test lane also loads them in an environment with only a registry install and no sibling checkout (CI). ### Upstream artifact freshness check `npm run harness:check` checks whether upstream build artifacts are up to date. The two checks are independent. 1. Declarations versus source: verifies that `lib/types/*.d.ts` is newer than the corresponding upstream source files, so type checking never reads an interface compiled from older source. Remedy: rebuild both the declarations and the Node-side artifacts. 2. Browser runtime versus declarations: verifies that a client package's `lib/client.js` is newer than its own client declarations, so the runtime the page loads is not older than the declarations the compiler read. Remedy: rebuild the browser artifacts only. ```sh pnpm --dir ../deepseek-harness run build # check 1: declarations and Node-side artifacts pnpm --dir ../deepseek-harness run build:lib:client # check 2: browser artifacts only ``` Without `--strict`, both checks print a note. With `--strict` (the mode `release:check` uses), both become errors that fail the run. Missing declarations fail in both modes because type checking cannot resolve them at all. The same script also gates the vendored framework packages: the floor of every `cordis`, `cosmokit`, `schemastery`, and `cordis-plugin-*` range in `dependencies` / `devDependencies` / `peerDependencies` must equal the version in the sibling's `vendor//package.json`, and a mismatch fails in both modes. These packages do not follow the harness pin, and a `^X.Y.Z-alpha.N` floor leaves two copies of `cordis` in one profile. ## Integration Tests ```sh npm run test:integration ``` Integration tests require a local Zotero instance running at `127.0.0.1:23119` with the Local API enabled. ## Build Artifacts - Node artifact (`lib/`): Compiled by `tsc`, containing service logic, tool definitions, provider, and transport layers. - Browser artifact (`lib/client.js`): Bundled by `esbuild`, containing the configuration page, Sources panel, and session cards. ## Local Debugging ### Full Plugin Debugging (with Web UI) ```sh export DSH_HOME=$(mktemp -d /tmp/dsh-zotero-dev-XXXX) cp ~/.dsh/.credentials.yaml "$DSH_HOME/" # seeds write credentials only; see the note below chmod 600 "$DSH_HOME/.credentials.yaml" npm run build dsh plugin --profile web add . npm run dev & # Watch Node-side changes npm run dev:client & # Watch browser-side changes cd ../deepseek-harness && env DSH_HOME="$DSH_HOME" \ node --import tsx/esm apps/cli/src/bin.ts web --port 3307 ``` > Note: since alpha.4 the plugin's configuration persists in the active profile's `cordis.patch.yml` (the `zotero` entry), and `~/.dsh/settings.yaml` is imported once at startup only. Fill the Zotero connection settings once in the temp instance's plugin manager under the **dsh-zotero** configuration section (or copy the `zotero` entry's `config` from one of your existing profiles' `cordis.patch.yml`). > Scholarly component: the `dsh-zotero/scholarly` row ships with the bundle disabled, and that row is its only switch. Both local overlay templates (`dev.cordis.yml.example` / `dev-lib.cordis.yml.example`) mount the scholarly component, so local debugging needs no toggle. In a real profile, enable the row under "Included components"; the tools and the settings page take effect without a restart. ### Host-Only Debugging (with HMR) ```sh npm run build # Initial build of lib/ npm run dev & # Watch and incrementally compile to lib/ cp dev-lib.cordis.yml.example dev-lib.cordis.yml # Copy template and fill absolute checkout paths dsh web --patch ./dev-lib.cordis.yml --port 3307 ``` > Note: the `dev-lib.cordis.yml` overlay points to the built entry using an absolute path (`/lib/index.js`), enabling in-process Loader HMR for the host half (tools and `/zotero` command) without restarting dsh. However, the harness web client module loader only resolves plugins registered under bare package names. Consequently, this mode does not load browser-side frontend modules (configuration page or Sources tab). To develop and test the UI, use the "Full Plugin Debugging" workflow above (`dsh plugin --profile web add .` and `npm run dev:client`). ### Diagnostics Panel and Diagnostics Bundle To inspect runtime behavior or investigate issues, enable "Diagnostic mode" in configuration; the "Diagnostics" card at the bottom of the **dsh-zotero** detail page shows runtime state and logs: - **Record retention and filtering**: When diagnostic mode is enabled, relevant events are collected with severity filtering available ("Problems" selects warn and error). Entries are listed in reverse chronological order, and consecutive identical messages are coalesced with a repeat counter; - **Diagnostic mode**: Enable "Diagnostic mode" in the "Diagnostics" group of the dsh-zotero configuration section and save to display the diagnostics card at the bottom and collect detailed troubleshooting records; - **Client crash reporting**: When browser-side components (such as the Sources tab, tool cards, or detail panels) encounter a render crash, error boundaries automatically log the event and identify the failing surface in the `surface` field (for example, `sources` or `tool:zotero_search`); - **Exporting records**: Clicking "Copy diagnostics" exports a text bundle containing the plugin version, Zotero endpoint and version, debug state, and all buffered log entries for bug reports. ## Testing Standards - Unit tests run against a mock Zotero HTTP service (`MockZotero`). - Browser configuration page tests use JSDOM and `@testing-library/react`. - Coverage thresholds are defined in `vitest.config.ts`, with separate gates enforced for each core layer. - Integration tests validate wire protocols and real data against an active Zotero instance. ## Release Checklist `release:check` in `package.json` defines the release gate. It runs steps 1 through 7 in order and stops at the first failure; step 8 is the manual verification outside the script: 1. `npm run format:check`: Prettier formatting check. 2. `npm run harness:check -- --strict`: version pin, upstream declarations, and vendored framework versions must align; stale artifacts become errors in this mode (`release:check` invokes the same script directly as `node scripts/harness-state.mjs --strict`). 3. `npm run lint:test`: test-specification guards (lanes, `.only`/`.skip`, spec line ratchet). 4. `npm run typecheck`: type checking across the Node, test, and client projects. 5. `npm run test:coverage`: the full vitest suite plus the per-layer coverage gates. 6. `npm run build`: production build (`tsc` → `lib/`, esbuild → `lib/client.js`). 7. `npm run verify:pack`: validate the required files in the packed tarball. 8. Verify golden path scenarios (G1 through G8) in [Scenarios](scenarios.en.md); verify W1 through W9 as well if write operations are enabled. `npm test` is not the release gate: it runs `node scripts/test-lint.mjs` plus `vitest run` without coverage thresholds, which is the day-to-day regression command. The release path splits those two concerns into steps 3 and 5.