Skip to content

DeepSeek Harness ships two CI surfaces (GitHub Actions for the TypeScript monorepo and its Python SDK; GitLab CI for the native Python wheels) plus a rich set of local developer toold — lefthook git hooks, oxlint, knip, jscpd, and the invariant/vendored-link hygiene gates. Releases follow family-based version bumps (release/dsh-* / release/vendor-*) and commit the version into the repository before a human tags. This page maps the whole engineering pipeline.

GitLab CI: Python release shape

.gitlab-ci.yml runs only for Python release tags (python-v<major>.<minor>.<patch>…). Two stages, build and publish:

  • sdk-wheel builds the keyless SDK wheel.
  • runtime-linux-x64, runtime-linux-arm64, runtime-macos-arm64 each build the bundled single-exe runtime for its target, then verify it: a Python smoke (python scripts/smoke-python-runtime.py), glibc <= 2.28 via readelf for Linux, manylinux smoke through a Docker image, and a macOS deployment-target check.
  • publish-python uploads the four .whl files to the project's Package Registry with twine, guarded by a tag-vs-package.json version assertion. GitLab does not overwrite an existing version, so each release needs a fresh python-v<version> tag.

The tag-vs-version guard is central: test "$CI_COMMIT_TAG" = "python-v$DSH_VERSION" || exit 1.

GitHub Actions: the PR gate

.github/workflows/ci.yml is the required pull-request pipeline. It is sophisticated about runner pools and concurrency; the key lanes (all Node 24 unless noted):

JobRunsWhat it does
node-24 / staticLinux enterprise poolpnpm run check:ci:static
node-24-coverageLinuxpnpm run check:ci:coverage (exhaustive coverage)
node-24-consumersLinuxpnpm run check:ci:consumers (snapshots, artifacts, Playwright-based web)
node-compat (matrix)ubuntu-latestNode 22.19 and 26: check:node-compat
python-sdkubuntu-latestPython 3.10 keyless suite via uv
python-runtimereusable buildrelease-shaped Linux x64 exe build
windowsubuntu-latestWine: runs scripts/wine-windows-gates.sh (Windows Node under Wine)
windows-nativereal Windowscheck:ci:windows-complete
serial-linux-selfhosted / serial-windowsself-hostedpush-only standby drills (hot-standby evidence for the failover pools)
all-checks-passedubuntu-latestif: always() aggregate verdict; fails on any non-success needed job

The gate scripts come from scripts/run-gates.ts. check:ci, check:ci:linux-primary, check:ci:static, check:ci:coverage, check:ci:snapshot, check:ci:artifacts, check:ci:consumers, and check:ci:windows-* are all thin npm-script sugar over separate run-gates.ts orchestrations. Env knobs bound concurrency: DSH_GATE_CONCURRENCY, DSH_COVERAGE_MAX_WORKERS, DSH_SNAPSHOT_MAX_CONCURRENCY, DSH_E2E_MAX_WORKERS, DSH_OXLINT_THREADS, DSH_PUBLINT_CONCURRENCY.

Notable CI policies baked into the workflow env: DSH_TELEMETRY_DISABLED=1 (CI runs never report to the production telemetry endpoint), fetch-depth for the archive gate, Playwright Chromium for the web gates, prepare-ci-bubblewrap.sh to unrestrict the namespace for the sandbox suites, and a failover mechanism via repository variables DSH_CI_FAILOVER_LINUX / DSH_CI_FAILOVER_WINDOWS that retarget jobs onto in-house self-hosted pools.

The release process (visible from git)

The release flow is versioned and tag-only:

bash
$ git log --oneline --grep=release -15
abe560f81e release(dsh)
8c1e8d9890 build(release): publish the dsh family publicly
8a954b2eca release(dsh): 0.1.0-rc.3
60b04b6ef7 release(dsh): 0.1.0-rc.2
22ab3beac1 release(dsh): 0.1.0-rc.1
7bedce822f release(vendor)

scripts/release/ implements it:

ScriptRole
bump.tsBump one family's version and commit it (--family dsh shares one version across members + root; --family vendor has one line per package but ships the whole family)
verify.tsVerify release version against the workspace state
pack.tsBuild and pack tarballs into a dist/npm dir
verify-packed-install.tsInstall the packed tarballs (plus vendor and Landlock tarballs) and prove they resolve
publish.tsUpload the exact packed bytes to npm

The .github/workflows/release.yml workflow runs release:verifybuildrelease:packrelease:verify-packed-install on every PR/push (a pack-only proof that the whole publish set still packs), then a separate manual publish job backed by the environment: npm-publish gate uploads the bytes when dispatched from a dsh-v* tag. The vendored framework family releases through its own release-vendor.yml; the Landlock native package through native/landlock-run. THIRD_PARTY_NOTICES.md is regenerated by lefthook whenever a dependency edit changes the payload.

Developer tooling

lefthook git hooks (lefthook.yml)

postinstall runs node scripts/install-lefthook.mjs. Local hooks are deliberately fast checkpoints; CI owns the full matrix:

  • pre-commit: staged-lint (tsx scripts/run-oxlint.ts --config .oxlintrc.staged.json), translation pairing for *.i18n.yaml, archived-agent-notes check, whitespace git diff --cached --check, vendor manifest guard, and third-party-notices regeneration (re-generates + git add THIRD_PARTY_NOTICES.md).
  • pre-merge-commit: translation pairing + archived notes.
  • pre-push: pnpm run typecheck.

oxlint (run-oxlint.ts, .oxlintrc.json)

npm run lint = build:lib:host then tsx scripts/run-oxlint.ts . (the contracts-ready variant runs after the client contract build). .oxlintrc.json turns correctness rules off at the top and re-enables strict, mostly type-aware rules scoped per override; it ignores vendor/**, native/**, and *.config.ts. There is a stricter --fix staged variant (.oxlintrc.staged.json) for the hook.

knip unused-code checks (knip.json)

npm run knip (knip --treat-config-hints-as-errors) detects unused dependencies/files/exports across the workspace. Vendor and python/sdk-runtime are ignored; several binaries (bwrap, icacls, musl-gcc, python3, sandbox-exec, tar, taskkill, where.exe) and deps (@yarnpkg/cli-dist, lightningcss) are whitelisted.

jscpd duplication (jscpd.json)

npm run duplication runs jscpd --config .jscpd.json packages scripts with minTokens: 60, minLines: 6, mode: "mild", and an ignorePattern for explicit /* jscpd:ignore-start */ … /* jscpd:ignore-end */ blocks (used heavily in invariant companions and exports).

hygiene bundle

pnpm run hygiene chains the deep gates: rescope-vendor:check, knip, publint, constraints, verify-dsh-package-licenses, verify-package-invariants, verify-built-package-invariants, verify-cordis-config, verify-node-next-types, verify-runtime-closure, verify-vendored-links. These guarantee the workspace is internally consistent before anything ships.

Contribution process

CONTRIBUTING.md states the project is early-stage and does not accept external pull requests yet; contributions happen through GitHub Discussions, ecosystem plugins (via the dsh-plugin topic), and community content. It is a deliberate gate that keeps PR review effort focused on the internal team while growing the ecosystem around the harness.

Tooling

ToolVersion (from root package.json devDependencies)
vitest^4.1.8
oxlint
oxlint-tsgolint
knip^6.16.1
jscpd^5.0.12
lefthook^2.1.9
tsx^4.22.4
typescript^6.0.3
publint^0.3.21
tsdown^0.22.2

Further reading

  • Testing strategy — what each check:ci:* gate actually runs.
  • Runtime invariants — the verify-package-invariants gate and companions.
  • Vendored librariesverify-vendored-links, rescope-vendor, and the family releases.
  • .gitlab-ci.yml — the Python wheel pipeline and its tag guard.
  • scripts/run-gates.ts and scripts/release/bump.ts — gate orchestration and family versioning.
  • lefthook.yml — the exact pre-commit/pre-push jobs and their globs.