# v0.5 Product Design — Runtime Verification Status: **implemented at repository level in v0.5.0**. ## Summary v0.4 lets humans, the in-process DSH Agent, and external MCP clients inspect the same live Cordis runtime. v0.5 extends that read-only diagnostic surface with **before/after runtime verification**. The milestone goal is: > A coding Agent can capture relevant runtime topology before a change, edit/reload code through the normal development workflow, compare the current runtime with the baseline, and report the concrete runtime facts that changed. v0.5 remains **read-only with respect to the target Cordis runtime**. It does not automatically enable the waterfall profiler, mutate listener registrations, reload plugins, or make root-cause/fix claims on behalf of the Agent. ## User experience ```text inspect current problem ↓ captureCheckpoint ↓ edit source / reload by normal development workflow ↓ compareCurrent(baseline) ↓ inspect changed facts when needed ↓ Agent explains whether the expected runtime condition is now present ``` Example: ```text Before SessionPlugin live Fiber multiplicity = 2 session/created listener multiplicity owned by SessionPlugin = 2 After SessionPlugin live Fiber multiplicity = 1 session/created listener multiplicity owned by SessionPlugin = 1 ``` The diagnostics layer reports those facts. It does not return `fixed: true`, `rootCause`, or a confidence score. ## Why a first-class checkpoint/diff layer exists An Agent could issue the v0.4 queries twice and manually compare them, but that has three problems: 1. runtime-local ids are noisy across lifecycle changes and reloads; 2. bounded dispatch/profiler history must not be confused with authoritative live state; 3. every Agent would otherwise reimplement matching, multiplicity, and unknown semantics. v0.5 therefore provides one canonical verification projection and diff algorithm shared by DSH Cordis Inspect and MCP. ## Core architecture ```text Cordis runtime │ ▼ DevtoolsService / observer facts │ ▼ RuntimeDiagnosticsQuery │ ├─────────────── targeted v0.4 reads │ ▼ Runtime Verification ├─ checkpoint projection ├─ canonicalization └─ semantic diff │ ├─────────────────────┐ ▼ ▼ CordisRuntime Inspect embedded MCP DSH Agent external Agent ``` The verification layer consumes existing project-owned runtime snapshots. It adds no direct Cordis-internal access outside `src/host/cordis-adapter.ts`. ## Checkpoint contract ### Self-contained, not server-persistent A checkpoint is a **serializable value returned to the caller**, not an opaque id stored by the Host. The v1 contract lives in `src/shared/verification.ts` and contains: ```ts interface RuntimeCheckpoint { schemaVersion: 1 capturedAt: number scope: RuntimeCheckpointScope digest: string events: RuntimeCheckpointEvent[] listeners: RuntimeCheckpointListener[] fibers: RuntimeCheckpointFiber[] } ``` This design: - avoids Host checkpoint TTL, ownership, persistence, and disconnect cleanup; - lets the caller carry a baseline across the normal edit/reload workflow; - keeps the DSH `cordisInspect` path read-only; - lets DSH and MCP expose the same canonical value; - keeps checkpoint comparison deterministic and testable as pure logic. ### Schema version and digest Every checkpoint carries schema version `1`. Comparison rejects unsupported versions rather than guessing compatibility. The digest is SHA-256 over the canonical checkpoint body. `compareCurrent` validates it before comparing, so malformed or tampered baselines fail explicitly. The digest is an integrity/equality field, not object identity evidence. ### Scope v0.5 supports optional exact-name scope: ```ts interface RuntimeCheckpointScope { eventNames?: string[] fiberNames?: string[] } ``` Rules: - omitted selectors capture current authoritative topology; - event selectors include matching events/listeners and their current owner Fibers; - Fiber-name selectors include matching live Fibers plus their current listener/event relationships; - both selectors use union semantics; - selectors are exact names, not regex/fuzzy matching; - normalized scope is stored in the checkpoint and reused automatically by `compareCurrent`; - relationship closure is deterministic and one-hop rather than an arbitrary object/service crawl. An explicitly empty selector remains distinguishable from an omitted selector. ## What belongs in a checkpoint A checkpoint contains **current authoritative topology** sufficient to verify: - event existence and live listener multiplicity; - listener event/order/flags plus capture-local owner evidence; - live Fiber multiplicity, state, parent, inject names, owned events and metadata-only Effects. Runtime-local listener ids, listener order, Fiber uids and owner uids are useful **inside one capture** as factual evidence. They are not automatically stable cross-checkpoint identity keys. ## What is excluded ### Bounded dispatch history Dispatch records are not checkpoint topology. They are a bounded occurrence window, not authoritative current state. Agents use `searchDispatches` separately and retain its `bounded` / `truncated` semantics. ### Profiler traces Profiler traces are also excluded. `profilerTraces` remains the separate retained-trace read path. ### Raw/sensitive payloads Checkpointing does not add raw event arguments, return values, errors, prompts, tool results, file contents, plugin config, credentials, or raw Effect functions/disposers. ## Cross-checkpoint identity The diff never assumes that runtime-local ids survive a lifecycle change. For example, this is not a safe conclusion: ```text uid 41 disappeared, therefore that exact plugin instance was fixed ``` Comparison is semantic and multiplicity-based. ### Listener semantic descriptor The implemented listener descriptor is: ```text event name owner Fiber name / no owner prepend global ``` The following remain capture-local evidence and are **excluded** from the cross-checkpoint semantic key: ```text listener id owner Fiber uid listener registration order ``` `order` is deliberately excluded because two otherwise equivalent duplicate registrations naturally occupy different runtime order positions. Including it would split a real duplicate topology into separate `1`-count groups and prevent the canonical `2 → 1` verification case. ### Fiber semantic descriptor Fiber grouping uses canonical factual metadata including: ```text Fiber name normalized state parent Fiber name / no parent sorted inject names sorted owned event names canonical metadata-only Effect structure ``` Fiber uid is excluded from the semantic key. Equal descriptors are compared as **multisets**. Duplicate equivalent runtime objects therefore remain visible as count `2`, rather than collapsing into one row or requiring arbitrary instance pairing. ## Diff contract The machine-facing operations are: ```ts captureCheckpoint(scope?) -> RuntimeCheckpoint compareCurrent({ baseline }) -> RuntimeCheckpointComparison ``` `compareCurrent`: 1. validates baseline schema and digest; 2. captures fresh current topology using the baseline scope; 3. compares semantic multisets; 4. returns the current checkpoint plus structured changes. Representative result: ```json { "changed": true, "baselineDigest": "...", "events": [ { "name": "session/created", "beforeListenerCount": 2, "afterListenerCount": 1, "delta": -1 } ], "listenerGroups": [ { "descriptor": { "event": "session/created", "ownerName": "SessionPlugin", "prepend": false, "global": false }, "beforeCount": 2, "afterCount": 1, "delta": -1 } ], "fiberGroups": [ { "descriptor": { "name": "SessionPlugin" }, "beforeCount": 2, "afterCount": 1, "delta": -1 } ] } ``` The contract preserves these rules: - multiplicity is explicit; - runtime-local id/uid/order churn does not become semantic identity by accident; - unsupported/tampered baselines fail explicitly; - no `fixed`, `rootCause`, or confidence field is produced; - an unchanged result means only that authoritative checkpoint topology is semantically equal for the captured scope. ## Agent-facing methods ### DSH Cordis Inspect The existing `CordisRuntime` Provider exposes seven read-only methods; v0.5 adds: ```text captureCheckpoint compareCurrent ``` DSH continues to use the first-party `cordis_inspect_list` / `cordis_inspect_query` path. The plugin does not register a second package-specific model-tool family. ### MCP The embedded MCP adapter exposes the matching tools: ```text cordis_capture_checkpoint cordis_compare_current ``` They delegate to the same `RuntimeDiagnosticsQuery` implementation as Cordis Inspect. MCP remains loopback-only and disabled by default; both tools are read-only and idempotent and never enable instrumentation. ## Real DSH verification proof The canonical v0.5 E2E uses a real Cordis fixture: ```text baseline runtime two same-name live Fibers two listeners for one event ↓ DSH Cordis Inspect captures baseline A external MCP captures baseline B ↓ real Cordis lifecycle transition one duplicate instance is disposed ↓ DSH compareCurrent(A) MCP compareCurrent(B) ↓ both independently report Event listeners 2 → 1 Listener semantic group 2 → 1 Fiber semantic group 2 → 1 ↓ Human DevTools / waterfall Profiler regression remains healthy ``` The proof uses the real DSH `cordisInspect` registry and an official external MCP SDK Client against the same running DSH process. It requires no model credential or API key and does not use runtime-local id/order equality as the verification result. ## Non-goals for v0.5 Explicitly deferred: - automatic plugin/source reload control; - `diagnose()` or model-independent root-cause heuristics; - server-persistent checkpoint ids/history; - persistent checkpoint files; - multi-runtime checkpoint discovery; - profiler enable/disable Agent tools; - profiling lease/timeout/permission logic; - remote/LAN MCP; - payload capture; - generic lossless telemetry. ## Why profiler mutation moves beyond v0.5 Profiler mutation has a different trust boundary: - it changes the runtime dispatch seam; - it needs permission policy; - it needs ownership/timeout cleanup if an Agent disappears; - it must handle conflict/unsupported instrumentation states. The product progression therefore stays clean: ```text v0.4 Agent can observe runtime facts v0.5 Agent can verify before/after runtime facts v0.6 Agent may perform controlled runtime experiments ``` ## Completion v0.5 is repository-ready because: - the checkpoint schema/canonicalization is versioned and tested; - semantic diff preserves duplicate multiplicity and excludes runtime-local id/uid/order from cross-checkpoint identity where required; - `captureCheckpoint` and `compareCurrent` are available through the shared query path; - DSH Cordis Inspect and MCP expose them through thin adapters over the same implementation; - one real DSH test proves duplicate runtime topology `2 → 1` through both Agent paths; - existing observer/UI/profiler behavior remains green; - repository metadata/docs close out at version `0.5.0`. Publishing npm, creating a Git tag, or creating a GitHub Release remains a separate explicit action.