Merge remote-tracking branch 'origin/master' into codex/trim-ai-prose
# Conflicts: # docs/AGENTS.md # docs/config-catalog.md # packages/bash/bash-sandbox/src/index.ts # packages/bash/bash/src/session-mode.ts # packages/bash/tool-bash/README.md # packages/code-runtime/code-runtime-worker/README.md # packages/compact/compact/src/index.ts # packages/core/agent-core/README.md # packages/hooks/hooks-claude/src/config.ts # packages/hooks/hooks-claude/src/index.ts # packages/hooks/hooks-codex/src/config.ts # packages/hooks/hooks-codex/src/index.ts # packages/llm/llm/README.md # packages/session-persistence/session-persistence-jsonl/README.md # packages/session-persistence/session-persistence/README.md # packages/skill/skill-local/README.md # packages/support/acp-snapshot/README.md # packages/support/invariants/src/index.ts # packages/ui/acp/README.md # packages/ui/jsonrpc-agent/README.md # packages/ui/jsonrpc/README.md # packages/ui/permission/README.md # packages/ui/user-approval/README.md # packages/ui/user-interaction/README.md # packages/web/web-search-deepseek/README.md
This commit is contained in:
@@ -5,8 +5,8 @@ Packages that exist to serve development, testing, and the examples rather than
|
||||
| Package | Role | ctx key |
|
||||
|---|---|---|
|
||||
| `acp-snapshot/` | ACP snapshot suite kit: subprocess scenario harness + golden normalizers + the `defineAcpSnapshotSuite` factory | (library — imported by example `*.snapshot.ts` suites) |
|
||||
| `invariants/` | Dev-mode event-contract assertions | (listens on `session/*`, `agent/*`) |
|
||||
| `invariants/` | Runtime event-contract assertions for development diagnostics | (listens on `session/*`, `agent/*`) |
|
||||
| `llm-replay/` | Record/replay adapter: short-circuits `llm/stream` from a recorded session JSONL (keyless snapshot tests) | (listens on `llm/stream`) |
|
||||
| `subagent-mock/` | Scripted `SubagentProvider` for deterministic seam/tool tests | (registers on `ctx.subagents`) |
|
||||
|
||||
`invariants` runs only in dev mode (contract checks, not runtime behavior). `llm-replay` backs the demos and the snapshot test tier under the per-file coverage gate. `acp-snapshot` carries the snapshot tier's harness/normalizer/suite machinery so every example's suite is a scenario table over one shared, gate-covered implementation. `subagent-mock` exercises the real `ctx.subagents` load path without a model or child agent. A package graduates OUT of `support/` into a product group only when it gains documented product consumers.
|
||||
`invariants` is development support but has no environment guard: it runs wherever registered, and the default `dsh-agent-core` bundle mounts it unconditionally. `llm-replay` backs the demos and the snapshot test tier under the per-file coverage gate. `acp-snapshot` carries the snapshot tier's harness/normalizer/suite machinery so every example's suite is a scenario table over one shared, gate-covered implementation. `subagent-mock` exercises the real `ctx.subagents` load path without a model or child agent. A package graduates OUT of `support/` into a product group only when it gains documented product consumers.
|
||||
|
||||
@@ -39,4 +39,13 @@ A scenario booting a differently-composed tree sets its own `configPath` (an ove
|
||||
|
||||
Examples use a `cordis.snapshot.yml` overlay with [`dsh-llm-replay`](../llm-replay/README.md). Recording calls the live model and updates model fixtures; keyless refresh replays those fixtures and updates derived stdout, session-log, and prompt snapshots. See the [snapshot RFC](../../../docs/rfc/implemented/testing/2026-06-19-acp-snapshot-tests.md).
|
||||
|
||||
`suite.ts` imports Vitest, so use this package only inside a Vitest run. The ACP-specific script can queue permission answers by stable option kind and can set session config options or assert their rejection in the transcript. Missing permission answers cancel; selecting an unavailable kind fails the scenario.
|
||||
`suite.ts` imports Vitest, so use this package only inside a Vitest run. The ACP-specific script queues permission answers by stable option kind and maps them to current option ids; a missing answer cancels, while an unavailable kind fails the scenario after cancelling the agent request. It can also set session config options or assert that unknown ids and values are rejected in the transcript.
|
||||
|
||||
## Model Experience
|
||||
|
||||
None, as this test-only harness records, normalizes, and compares ACP transcripts without changing the agent's assembled model request.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **Session harvest is JSONL-only** — `runScenario` collects persisted `.jsonl` logs, so an example composed over the SQLite persistence backend has no snapshot path.
|
||||
- **The subprocess boots the unbuilt tsx/Loader path only** — the built-bin artifact is guarded by the separate `built-bin` e2e smokes, never by this tier.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# dsh-invariants
|
||||
|
||||
Dev-mode event-contract assertions. This pure-listener plugin checks relationships among session events, agent states, scoped dispatches, and model requests at runtime; it does not own or change product behavior.
|
||||
Runtime event-contract assertions intended for development diagnostics. This pure-listener plugin checks relationships among session events, agent states, scoped dispatches, and model requests; it does not own or change product behavior.
|
||||
|
||||
**Off in production.** Enable it in tests and the demos, where a contract violation should fail loudly. It costs nothing when not registered, and doubles as executable documentation of the event taxonomy — the assertions *are* the contract.
|
||||
The plugin has no environment guard: it is active wherever it is registered. The default [`dsh-agent-core`](../../core/agent-core/README.md) bundle mounts it unconditionally; a custom composition can omit it when the runtime cost is undesirable. It doubles as executable documentation of the event taxonomy — the assertions *are* the contract.
|
||||
|
||||
Session itself owns immutable log storage in every composition: it takes one lossless JSON snapshot of each accepted event, deep-freezes that record, and exposes the log through immutable array snapshots. The invariants plugin checks the cross-record and cross-seam rules that storage immutability cannot express.
|
||||
|
||||
@@ -45,8 +45,17 @@ On any violation it throws `InvariantError` (`code: 'INVARIANT'`).
|
||||
|
||||
## Why runtime assertions remain useful
|
||||
|
||||
Session enforces the per-record storage boundary at runtime, where a cast cannot bypass it. Pervasive `DeepReadonly<SessionEvent>` types would add noise across consumers without expressing relationships such as turn/step nesting, subject-correct scoped dispatch, or equality between a request and its log reconstruction. This plugin checks those relationships in development while `dsh-session` keeps history immutable in every composition. See [source-owned session immutability and dev-mode invariants](../../../docs/rfc/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md).
|
||||
Session enforces the per-record storage boundary at runtime, where a cast cannot bypass it. Pervasive `DeepReadonly<SessionEvent>` types would add noise across consumers without expressing relationships such as turn/step nesting, subject-correct scoped dispatch, or equality between a request and its log reconstruction. This plugin checks those relationships wherever it is mounted while `dsh-session` keeps history immutable in every composition. See [source-owned session immutability and dev-mode invariants](../../../docs/rfc/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md).
|
||||
|
||||
## Seeded sessions
|
||||
|
||||
A seeded or forked session arrives with events already in its log because construction does not emit `session/event` for each seed record. `Session` validates, snapshots, and freezes every seed record before accepting it; on `session/created`, this plugin replays the accepted log only to rebuild and check its relational trace state.
|
||||
|
||||
## Model Experience
|
||||
|
||||
None, as this observer only validates events and frozen requests and never rewrites prompts, schemas, messages, or streams.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **The request-reconstructability assertion covers loop-built requests only** — hand-built one-shots (e.g. compaction's summarize call) carry no live `sessionId` marker and are skipped.
|
||||
- **Merge-extended event families get no family-specific assertions** — `compact/*` lock pairing and `hook/*` invoked/result pairing are not checked here; only the core turn/step/chunk/tool-result contract is.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-invariants",
|
||||
"description": "Dev-mode event-contract assertions for the DeepSeek Harness",
|
||||
"description": "Runtime event-contract assertions for DeepSeek Harness development diagnostics",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* Dev-only listeners for relationships that event types and immutability cannot express: turn and
|
||||
* step nesting, scoped dispatch, status transitions, and request reconstruction. Enable in tests
|
||||
* and demos, not production. Sessions already snapshot and freeze individual events; this plugin
|
||||
* checks the cross-event contract and serves as its executable documentation.
|
||||
* Runtime listeners that fail loudly when cross-event contracts are broken:
|
||||
* turn and step nesting, scoped dispatch, status transitions, and request
|
||||
* reconstruction. The plugin has no environment guard and is active wherever
|
||||
* mounted, including the default `dsh-agent-core` bundle; custom compositions
|
||||
* may omit it. Sessions still own event snapshots and freezing.
|
||||
* @module @deepseek-ai/dsh-invariants
|
||||
*/
|
||||
|
||||
@@ -329,7 +330,7 @@ function checkTransition(from: AgentStatus | undefined, to: AgentStatus): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the dev-mode invariants. Contributions are effect-scoped, so
|
||||
* Register the runtime invariants. Contributions are effect-scoped, so
|
||||
* disposing the plugin fiber removes all listeners (HMR-safe). On (re-)apply
|
||||
* the trace state is rebuilt by replaying each existing session's log, so a
|
||||
* hot reload mid-turn does not falsely reject the next event.
|
||||
|
||||
@@ -43,3 +43,12 @@ Replay keys every call by its calling session id (`GenerateOptions.sessionId`, s
|
||||
## Plugin export shape
|
||||
|
||||
Named `name` / `inject` / `Config` / `apply`, with **no default export**: the cordis Loader's `unwrapExports` does `exports.default ?? exports`, so a stray default would collapse the module to the bare function and drop the `inject` namespace (see [docs/postmortem/0001](../../../docs/postmortem/0001-acp-default-export-drops-inject.md)).
|
||||
|
||||
## Model Experience
|
||||
|
||||
None, as this keyless test adapter sends no request to a provider model; it only replays recorded assistant chunks into the test loop.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **First-call-order script binding assumes sequential delegation** — a cut that runs sibling subagents concurrently (or a compaction summarize call landing mid-run) would bind live sessions to recorded scripts non-deterministically; a stronger keying is deferred until such a scenario exists (`XXX(concurrent-subagents)`).
|
||||
- **Only chunk-producing calls are derivable** — a pure pre-chunk throw or a cancel/hang scenario needs the `replay.override.json` sidecar; the override replaces the PRIMARY session's script only.
|
||||
|
||||
@@ -18,3 +18,12 @@ Load it as a plugin (functional shape: `name`/`inject`/`Config`/`apply`, no defa
|
||||
| `structured` | `{ reply }` | Structured value surfaced when a request carries an `outputSchema` and the capability is on. |
|
||||
|
||||
Aborting the required request signal or disposing before `result` settles flips the stop reason to `aborted`, so both holder-facing cancellation paths are observable.
|
||||
|
||||
## Model Experience
|
||||
|
||||
Indirectly, through `dsh-tool-subagent`, which renders this test provider's configured reply or stop-reason error into the parent test history.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **Scripted provider only** — it does not run a model, create a child agent, or exercise real prompt/tool-loop behavior.
|
||||
- **One synthetic outcome per run** — it models no multi-turn, streaming, steering, resume, or subprocess transport behavior.
|
||||
|
||||
Reference in New Issue
Block a user