Skip to content

[AI-2020] DeepSeek Harness (dsh) vendor — CLI hook, watcher/import wiring, plugin scaffold - #583

Open
Lougarou wants to merge 8 commits into
mainfrom
spike/deepseek-harness
Open

[AI-2020] DeepSeek Harness (dsh) vendor — CLI hook, watcher/import wiring, plugin scaffold#583
Lougarou wants to merge 8 commits into
mainfrom
spike/deepseek-harness

Conversation

@Lougarou

Copy link
Copy Markdown
Contributor

CLI side of DeepSeek Harness (dsh) vendor support — part of AI-2020. Pairs with the kcap-server PR.

What

  • DshHookCommand — live-capture dispatcher (session-start and session-end). Start POSTs /hooks/session-start/dsh and ensures the watcher tailing the session's session.jsonl; end kill+drains (capped) then POSTs /hooks/session-end/dsh. dsh is event-sourced, so the watcher tails the on-disk stream directly — no SDK fetch/JSONL synthesis.
  • Vendor-generic wiringWatchCommand.KnownVendors, SessionStartHarness.Dsh + HarnessToken, VendorSelection --dsh (+ prefix guards), Program.cs hook dispatch + usage + KCAP_SKIP fast-path.
  • DshImportSource — historical import mirroring the Kiro JSONL-per-session pattern (per-dir <sessions>/<id>/session.jsonl, cwd/created-at from the {type:"session"} header line, server-watermark completeness, no client ledger). Registered in both source lists.
  • DshPaths + DshExtensionInstaller — installer mechanics (install/remove/version-marker), env-overridable path (KCAP_DSH_HOME).
  • Docs — help-hook.txt, help-import.txt, README note.

Tests (all green)

VendorSelectionTests (+dsh), DshImportSourceTests (8), DshPathsTests (2), DshExtensionInstallerTests (2). AOT publish: zero IL2xxx/IL3xxx warnings from dsh code.

Deferred — gated on external unknowns about dsh

DshExtensionInstaller's embedded plugin body is a documented placeholder: dsh's real Cordis plugin format/discovery-dir + MCP grammar are unconfirmed, so it is intentionally not wired into kcap plugin install/the setup wizard (auto-installing a non-functional plugin would mislead). A hand-written dsh plugin invoking the kcap hook --dsh contract works end-to-end today. DshPaths' default (~/.deepseek/harness/sessions/<id>/session.jsonl) is a placeholder pending the real on-disk location.

Draft — pairs with the server PR; the server's src/cli pointer should be re-pointed to this branch's merged-main SHA before the server PR merges.

🤖 Generated with Claude Code

…ing, plugin scaffold

Live capture: DshHookCommand (session-start + session-end); watcher
KnownVendors, VendorSelection --dsh, hook dispatch, SessionStartHarness.
Import: DshImportSource (Kiro JSONL-per-session pattern, server-watermark),
registered in both source lists. DshPaths + DshExtensionInstaller mechanics
(embedded plugin body is a documented placeholder pending dsh's Cordis API).
Unit tests: VendorSelection, DshImportSource, DshPaths, DshExtensionInstaller.
Docs: help-hook, help-import, README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Aug 18, 2026

Copy link
Copy Markdown

AI-2020

@Lougarou

Copy link
Copy Markdown
Contributor Author

Pairs with the server side: kurrent-io/kcap-server#1506

Lougarou and others added 7 commits August 21, 2026 12:36
…ll-stack verified)

Docker integration test against the real captured dsh sessions surfaced an id-split
bug: dsh ids are non-GUID ("session-<uuid>"), which CanonicalSessionId.Normalize
leaves dashed, but the CLI pre-stripped dashes for the transcript while the lifecycle
used the raw id — splitting each session into two streams (one with events, one with
the terminal). Fix: send the RAW id for both transcript and lifecycle (DshHookCommand
+ DshImportSource); the server canonicalizes uniformly.

Also corrected against the real deepseek-harness plugin (kcap-dsh.mts): sessions live
flat at ~/.cache/kcap/dsh/{id}.jsonl (was a guessed per-dir layout); DshPaths points
there + at $DSH_HOME/kcap-dsh.plugin.mjs; DshExtensionInstaller now embeds the real
Cordis plugin; DshImportSource reads the {$kcap:"header"} line for cwd. Help/README
paths corrected.

Verified end-to-end in Docker: `kcap import --dsh --all` of 4 real dsh sessions ->
one stream each, ended, vendor=dsh, model=deepseek/deepseek-v4-flash, tools+tokens
with failure detection (extensions.dsh.success) intact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… repo on import

Docker integration test surfaced that real dsh ids ("session-<guid>", 44 chars) are
filtered out of every read-model query by the pervasive length(session_id) <= 36 guard.
DshSessionId.Canonicalize extracts the embedded GUID (dashless, 32 chars) so a dsh
session keys like every other vendor and lists; applied identically in DshHookCommand
(live) and DshImportSource (import) so transcript + lifecycle converge on one stream.
Once <=36, the owner arm surfaces the session regardless of repo/visibility.

DshImportSource now enriches the session-start payload with git repo info
(EnrichWithRepositoryInfo) so imported sessions group under their repo, matching the
live hook. Unit tests for the canonicalizer + a session-<guid> discovery case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ranscript header

A dsh subagent child names its parent inline (transcript header parentSession +
origin=subagent). DshSessionHeader now reads parentSession; DshImportSource forwards it
(canonicalized) as parent_session_id, and DshHookCommand reads it from the child file for
the live path. Unit test for header parent extraction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
….patch.yml registration)

Installs the Cordis observer plugin to $DSH_HOME/kcap-dsh.plugin.mjs and registers it in
each profile's live-watched cordis.patch.yml via an idempotent, marker-delimited managed
block (drops a lone `[]`, preserves user entries + comments; remove strips it). Only the
dependency-free file:// observer plugin is auto-registered; the MCP entries (which depend on
the dsh-mcp-client bundle) stay documented to avoid a fail-loud boot. DshPaths.ProfilesDir/
CordisPatch added. Unit tests for idempotent register/unregister + user-entry preservation.

Verified against a real ~/.dsh: plugin written, registered in capacitor/headless/web, and
each cordis.patch.yml parses as a valid YAML array with the kcap insert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… new harness framework

Resolves the 236-commit drift. Conflicts (README, help-plugin, PluginCommand usings,
VendorSelection.KnownVendorFlags, moved VendorSelectionTests) resolved keeping both sides.
Integrated dsh into main's refactored harness framework: HarnessCatalog entry + AgentDetection
(Dsh result field, DshHome input, detect arm) + DshPaths *Pure helpers, so the new
HarnessCatalogConformanceTests passes. Implemented IImportSource.AttachesChildContentOnReplay
(false) and updated the ShouldSpawnAfter(outcome, baseUrl) call. Build clean; dsh + conformance
+ vendor-selection + nudge tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…coverage tests

- Remove AI-#### references from dsh C# files (repo lint: no Linear IDs in source)
- AgentDetectionResult constructions: add the new required Dsh arg
  (AgentsImportStepsTests, HarnessCatalogTests)
- Bump hardcoded vendor counts 9 -> 10 (HarnessInventoryTests, HarnessCatalogTests,
  AgentsImportStepsTests agent+import rows); add dsh to the per-selector detection test
- FlowsDriverSchemaConformance: exempt --dsh (ingest-only Cordis plugin, no kcap MCP
  config, so no flows driver schema — like --pi)
- ReplayChildContentCapability: classify DshImportSource (AttachesChildContentOnReplay=false)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SessionStartVisibilityTests + DaemonStatusReportTests assert the harness
inventory vendor count; dsh makes it ten.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Lougarou
Lougarou marked this pull request as ready for review August 21, 2026 23:36
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant