# Configuration

The guard plugin row (`id: medseek-guard`) accepts:

| Key | Type | Default | Meaning |
|---|---|---|---|
| `mode` | `block` \| `ask` \| `off` | `block` | What the PHI gate does on an identifier hit |
| `networkTools` | string[] | the four lookup tools + dsh web tools | Tool names screened by the gate |

Both keys are editable live in the web GUI under Settings > Plugins > MedSeek
(writes are revision-fenced and apply without a restart), or statically in the
profile `cordis.patch.yml`.

The tools plugin row (`id: medseek-tools`) accepts:

| Key | Type | Default | Meaning |
|---|---|---|---|
| `requestTimeoutMs` | number | 10000 | Per-request timeout for reference APIs |
| `maxResults` | number | 5 | Default PubMed page size (hard cap 10) |
| `maxSectionChars` | number | 4000 | Label-section truncation |
| `ncbiApiKey` | string | unset | NCBI E-utilities key |
| `openFdaApiKey` | string | unset | openFDA key |

Override in the profile `cordis.patch.yml` after the bundle layer. A patch
replaces the whole `config` object, so restate every key you care about:

```yaml
- id: medseek-tools
  config:
    requestTimeoutMs: 15000
    maxResults: 8
    maxSectionChars: 4000
    ncbiApiKey: YOUR_KEY
```

The guard row (`id: medseek-guard`):

| Key | Type | Default | Meaning |
|---|---|---|---|
| `mode` | `block` / `ask` / `off` | `block` | Deny, ask the user, or disable screening |
| `networkTools` | string[] | the four lookup tools plus `web_search`, `web_fetch` | Names to screen |

`off` is for development against synthetic data only.

The audit row (`id: medseek-audit`) accepts:

| Key | Type | Default | Meaning |
|---|---|---|---|
| `mode` | `on` \| `off` | `on` | Whether tool executions append compliance receipts |

With `mode: on`, every tool execution appends one line to
`medseek-audit.jsonl` in the dsh home (explicit override > `$DSH_HOME` >
`~/.dsh`, the same root dsh itself uses - never the working directory).
Lines carry sequence number, timestamp, tool name, call id, error flag,
and SHA-256 digests of the arguments and result content - never the
content itself. Appends serialize across processes through upstream's
bounded writer lock (`<file>.lock`, 2 s deadline); a dropped or
fail-closed receipt surfaces only as a content-free `medseek-audit:`
warning on stderr. See [permissions-and-data.md](permissions-and-data.md)
for the exact record and recovery steps.

Override statically in the profile `cordis.patch.yml`, restating the whole
config object:

```yaml
- id: medseek-audit
  config:
    mode: off
```

## Persona and the medseek-clinical preset

The clinical persona is deployed at two layers, because dsh applies personas
at two layers:

| Surface | Persona source | Why |
|---|---|---|
| Headless runs, TUI | `system-prompt` config in cordis.patch.yml | These surfaces mount no agent presets, so the deployment persona applies |
| Web sessions | `medseek-clinical` preset | A default web session joins an agent preset, and a preset persona shadows the deployment persona |

The bundle ships `agent-presets/medseek-clinical/` (the upstream `standard`
composition with only the persona text replaced) and a `medseek-preset-sync`
row that provisions it into `$DSH_HOME/.agent-presets/medseek-clinical/` on
every boot. The sync is atomic, idempotent, and deployment-owned: a locally
edited copy of the managed preset is restored on the next boot **with a
boot-log warning naming every restored file**; presets you author beside it
are never touched. Removing MedSeek leaves the last provisioned copy in
place - delete that directory to drop it.

A configured package root was not an option: the CLI recomposes the
agent-presets row on every boot and replaces its `roots` wholesale
(`apps/cli/src/profile-boot.ts`, `composeProfile` in `@deepseek-ai/dsh`),
silently dropping any roots a patch layer adds while keeping other keys.
Until upstream concatenates instead of replacing, provisioning through the
user root is the supported seam (draft issue text:
[UPSTREAM-ISSUE-DRAFT.md](https://github.com/Mr-Neutr0n/dsh-medseek/blob/main/UPSTREAM-ISSUE-DRAFT.md)
on GitHub - not included in the npm package).

Uninstall note: removing the plugin does not remove the provisioned preset.
Delete `$DSH_HOME/.agent-presets/medseek-clinical/` yourself, or switch the
default preset, so removed deployments do not keep answering as MedSeek.

To run a different preset for one session, pick it explicitly in the UI or
API; the default only governs sessions that name none.
