triss-coworker 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,79 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.35.0] — 2026-08-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `triss-dsh-provider-bundle`, a standalone npm package (workspace
|
|
15
|
+
`packages/dsh-provider-bundle`) that activates the DeepSeek Harness
|
|
16
|
+
`llm-pi-ai` adapter for `opencode`, `opencode-go`, and `zai` routes in a
|
|
17
|
+
`dsh` profile without changing the Harness default provider or model.
|
|
18
|
+
- Release gates publish and registry-verify both packages from one
|
|
19
|
+
coordinated tag (`scripts/publish-gate.js`, updated `publish.yml`), and a
|
|
20
|
+
dedicated CI bundle matrix covers Node `22.19.0`, `24`, and `26` plus
|
|
21
|
+
`pnpm`-missing diagnostics.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- `test/coder-init-credential-gate-blocker.test.js` pins
|
|
26
|
+
`TRISS_PROJECT_ROOT` to the temp HOME so credential-gate isolation no
|
|
27
|
+
longer depends on cwd lookups; no runtime code changed in this release
|
|
28
|
+
train (an earlier iteration of this PR touched `src/safety.js` and was
|
|
29
|
+
reverted for expanding the sandbox boundary).
|
|
30
|
+
- The publish workflow plans publication from live registry state for BOTH
|
|
31
|
+
packages (`plan-publish`), skips a publish step when the registry already
|
|
32
|
+
holds the byte-identical tarball, and registry-verifies both packages again
|
|
33
|
+
after publication — a partial-failure rerun is now safe, including after
|
|
34
|
+
`main` has moved past the tag (fresh releases require the exact
|
|
35
|
+
`origin/main` tip; retries only require the tag to remain an ancestor,
|
|
36
|
+
via `publish-gate.js authorize-tag`).
|
|
37
|
+
- The tag workflow separates privileges: an unprivileged `release-gates`
|
|
38
|
+
job runs every repository-script verification (versions, tarball
|
|
39
|
+
inspection, registry planning, tag authorization) and only a minimal
|
|
40
|
+
`npm-publish` job behind the `npm-production` environment holds
|
|
41
|
+
`id-token: write`. The publish job repacks with `--ignore-scripts` and
|
|
42
|
+
byte-compares both tarballs against the gates artifact before publishing
|
|
43
|
+
the same bytes with `--provenance`.
|
|
44
|
+
- CI gains a required `dsh plugin lifecycle` job (real `@deepseek-ai/dsh`
|
|
45
|
+
0.1.0-rc.6 + pnpm 9): add → real in-place update (add v2 over v1, no
|
|
46
|
+
remove) → remove → reinstall → npx-style anchor, asserting the dumped
|
|
47
|
+
`llm-pi-ai.config.providers` object (exact provider set and `apiKeyEnv`
|
|
48
|
+
mapping) plus the profile manifest at every phase. The job lives in a
|
|
49
|
+
reusable `bundle-checks` workflow included by both PR CI and the tag
|
|
50
|
+
publish flow, and a post-publish `registry-acceptance` job installs the
|
|
51
|
+
published package from the registry on Node `22.19.0` and `24`, exercises
|
|
52
|
+
add/update/remove/reinstall, and records the compatibility tuple with
|
|
53
|
+
registry integrity and provenance evidence.
|
|
54
|
+
- `npm test` now runs `scripts/check-lockfile-gate.cjs`, which asserts the
|
|
55
|
+
workspace name/version/engines against the live manifests plus the
|
|
56
|
+
pinned `@deepseek-ai/dsh-app-boot`.
|
|
57
|
+
|
|
58
|
+
### Unchanged
|
|
59
|
+
|
|
60
|
+
- Triss runtime code, CLI, MCP schemas, and the root `triss-coworker`
|
|
61
|
+
published-file allowlist; the root tarball contains no companion manifest
|
|
62
|
+
or patch. (Correction, review finding: the follow-up fix commit DID touch
|
|
63
|
+
`src/safety.js` — `projectRoot()` was extended to `.codex/worktrees`,
|
|
64
|
+
widening the restricted-mode sandbox boundary to sibling worktrees. That
|
|
65
|
+
change is REVERTED in this corrective release; only the test-isolation
|
|
66
|
+
env pin from that commit remains.)
|
|
67
|
+
|
|
68
|
+
### Artifact integrity (0.35.0)
|
|
69
|
+
|
|
70
|
+
- `triss-dsh-provider-bundle-0.35.0.tgz` — sha256
|
|
71
|
+
`25d9d80417c7955ac29d933cdb9c3c5e412e0a6a3ebc2f73de852985ce2a4900`,
|
|
72
|
+
integrity `sha512-7NkUhHg+RruXEAJhMXr1nWlFv7g7N2iAh0z416oTS7yK/PPi4GnE8h8LqJOzFrGr86BUPHMhVmYinNe8cF6YZQ==`
|
|
73
|
+
(computed with the pinned release npm 11.6.2 via
|
|
74
|
+
`scripts/publish-gate.js pack-inspect`; `npm pack` output is
|
|
75
|
+
byte-deterministic — tar entries carry the fixed npm epoch mtime — so a
|
|
76
|
+
test pins this value against every future pack of the same content).
|
|
77
|
+
- Root `triss-coworker-0.35.0.tgz` sha256 is reproducible via
|
|
78
|
+
`npm pack` at tag `v0.35.0` (the root tarball ships `CHANGELOG.md`, so its
|
|
79
|
+
hash cannot be recorded inside this file); registry verification compares
|
|
80
|
+
the packed artifact against the published tarball byte-for-byte
|
|
81
|
+
(`scripts/publish-gate.js pack-inspect`).
|
|
82
|
+
|
|
10
83
|
## [0.34.0] — 2026-08-13
|
|
11
84
|
|
|
12
85
|
### Added
|
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
# DeepSeek Harness provider bundle and ecosystem proposal plan
|
|
2
|
+
|
|
3
|
+
Implementation contract for an opt-in DeepSeek Harness bundle that activates existing OpenCode and Z.AI catalogue routes without hand-written provider profiles.
|
|
4
|
+
|
|
5
|
+
## Status and verified baseline
|
|
6
|
+
|
|
7
|
+
This plan was verified against `deepseek-ai/deepseek-harness` commit `47f943859bef60e4160492346772ded9b24f765a` on 2026-08-14.
|
|
8
|
+
|
|
9
|
+
At that commit, `@deepseek-ai/dsh-llm-pi-ai@0.1.0-rc.5` declares `@earendil-works/pi-ai` with the semver range `^0.82.1`; the inspected upstream `pnpm-lock.yaml` resolves `pi-ai@0.82.1`.
|
|
10
|
+
|
|
11
|
+
The resolved `pi-ai@0.82.1` catalogue contains the `opencode`, `opencode-go`, and `zai` provider ids.
|
|
12
|
+
|
|
13
|
+
Its `opencode-go` catalogue contains `deepseek-v4-flash`, `deepseek-v4-pro`, `glm-5.1`, and `glm-5.2`, while its `opencode` catalogue contains `deepseek-v4-flash` and other models.
|
|
14
|
+
|
|
15
|
+
The Harness base bundle mounts `@deepseek-ai/dsh-llm-pi-ai` with no active routes and exposes its catalogue providers through the configurable-provider directory.
|
|
16
|
+
|
|
17
|
+
The missing product layer is an installable provider-profile bundle, not another LLM transport adapter.
|
|
18
|
+
|
|
19
|
+
The current Harness `CONTRIBUTING.md` does not accept external pull requests.
|
|
20
|
+
|
|
21
|
+
The supported contribution route is a community ecosystem plugin, a GitHub Discussion, and the `dsh-plugin` repository topic.
|
|
22
|
+
|
|
23
|
+
The npm registry returned `E404` for `triss-dsh-provider-bundle` during planning, but absence is not a reservation; availability must be checked again immediately before publication.
|
|
24
|
+
|
|
25
|
+
## Accepted decisions
|
|
26
|
+
|
|
27
|
+
- Build a configuration-only `dsh.bundle`; do not duplicate endpoints, protocols, model catalogues, or authentication logic owned by `pi-ai`.
|
|
28
|
+
- Publish the bundle under the distinct npm identity `triss-dsh-provider-bundle`.
|
|
29
|
+
- Develop and release the companion package from the Triss repository and coordinated Triss release train, while keeping it out of the `triss-coworker` tarball.
|
|
30
|
+
- Activate three catalogue routes in v1: OpenCode Zen (`opencode`), OpenCode Go (`opencode-go`), and direct Z.AI (`zai`).
|
|
31
|
+
- Reuse `OPENCODE_API_KEY` for both OpenCode routes and use `ZAI_API_KEY` for direct Z.AI.
|
|
32
|
+
- Leave the Harness default provider and model unchanged because the bundle cannot infer the user's entitlement or preferred route.
|
|
33
|
+
- Treat provider ids and credential references as the stable bundle contract.
|
|
34
|
+
- Treat exact model ids as release evidence for the dependency version actually resolved during acceptance, not as an independently maintained catalogue.
|
|
35
|
+
- Publish and maintain the bundle as a standalone community ecosystem plugin.
|
|
36
|
+
- Propose possible official adoption through a GitHub Discussion; prepare an upstream PR only after a direct maintainer invitation or an upstream contribution-policy change.
|
|
37
|
+
- Keep Triss runtime, coder-engine, CLI, MCP, templates, and provider routing unchanged.
|
|
38
|
+
|
|
39
|
+
## Why the bundle needs a separate package identity
|
|
40
|
+
|
|
41
|
+
Harness resolves every bundle from the running `dsh` installation before it tries the profile's `node_modules`.
|
|
42
|
+
|
|
43
|
+
The same resolver is used after `dsh plugin add` to decide whether an installed dependency declares `dsh.bundle`.
|
|
44
|
+
|
|
45
|
+
Publishing the bundle inside `triss-coworker` would make a globally installed Triss package eligible at the installation-first anchor before the profile-local version.
|
|
46
|
+
|
|
47
|
+
An older global Triss without the manifest could make the profile dependency look bundle-less, while a different global bundled version could load the wrong patch.
|
|
48
|
+
|
|
49
|
+
The distinct identity `triss-dsh-provider-bundle` prevents an ordinary global `triss-coworker` installation from colliding with the profile bundle lookup.
|
|
50
|
+
|
|
51
|
+
The companion package must be installed only into Harness profiles; globally installing the companion package is unsupported because it would recreate an installation-anchor ambiguity for its own name.
|
|
52
|
+
|
|
53
|
+
## Goals
|
|
54
|
+
|
|
55
|
+
- Let a Harness user install one profile dependency instead of authoring an `llm-pi-ai.providers` mapping.
|
|
56
|
+
- Make one OpenCode credential reference available to both Zen and Go without copying the secret.
|
|
57
|
+
- Expose DeepSeek V4 and GLM 5.x through the model catalogue resolved by the user's Harness installation.
|
|
58
|
+
- Support direct Z.AI GLM access through the catalogue-owned `zai` route.
|
|
59
|
+
- Keep credentials in Harness credential sources and references, never in bundle configuration or package contents.
|
|
60
|
+
- Keep the community package close enough to a possible official bundle that future adoption requires repository integration rather than a behavioral rewrite.
|
|
61
|
+
- Prove package resolution, configuration layering, provider routing, model selection, and tool use before publication.
|
|
62
|
+
- Release the companion package through the same reviewed Triss version and tag while preserving its separate npm identity.
|
|
63
|
+
|
|
64
|
+
## Non-goals
|
|
65
|
+
|
|
66
|
+
- Adding a `deepseek-harness` engine to `triss coder` in this change.
|
|
67
|
+
- Embedding `dsh.bundle` metadata or bundle assets in `triss-coworker`.
|
|
68
|
+
- Replacing OpenCode or changing existing Triss OpenCode and Z.AI behavior.
|
|
69
|
+
- Forking or patching `pi-ai` provider implementations.
|
|
70
|
+
- Maintaining a second model catalogue in this repository.
|
|
71
|
+
- Selecting a default provider, model, reasoning effort, or tool policy for a Harness profile.
|
|
72
|
+
- Buying subscriptions, enabling regional hosting, changing privacy settings, or treating a configured key as proof of entitlement.
|
|
73
|
+
- Supporting arbitrary custom providers in v1; Harness already exposes that through settings and patch layers.
|
|
74
|
+
- Creating an upstream pull request while upstream policy rejects external PRs.
|
|
75
|
+
- Publishing an npm version, GitHub tag, GitHub Discussion, or future upstream PR without separate authorization for that external action.
|
|
76
|
+
|
|
77
|
+
## Package and release topology
|
|
78
|
+
|
|
79
|
+
The repository becomes an npm workspace with the existing root package and one publishable companion package:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
packages/dsh-provider-bundle/
|
|
83
|
+
├── package.json
|
|
84
|
+
├── cordis.patch.yml
|
|
85
|
+
├── README.md
|
|
86
|
+
└── LICENSE
|
|
87
|
+
|
|
88
|
+
test/
|
|
89
|
+
└── dsh-provider-bundle.test.js
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The root `package.json` adds `packages/dsh-provider-bundle` to `workspaces` but does not add the companion to `files`, dependencies, optional dependencies, or bundled dependencies.
|
|
93
|
+
|
|
94
|
+
The root `triss-coworker` tarball therefore remains the Triss CLI package and contains no Harness manifest or bundle patch.
|
|
95
|
+
|
|
96
|
+
The companion manifest declares:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"name": "triss-dsh-provider-bundle",
|
|
101
|
+
"version": "<release-version>",
|
|
102
|
+
"type": "module",
|
|
103
|
+
"files": ["cordis.patch.yml", "README.md", "LICENSE"],
|
|
104
|
+
"engines": { "node": "^22.19.0 || >=24.0.0" },
|
|
105
|
+
"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The companion has no JavaScript entry point, runtime dependency, peer dependency, build output, `prepare`, preinstall, install, postinstall, or second release script.
|
|
110
|
+
|
|
111
|
+
The root and companion manifests use the same selected release version and are published from one exact `v<version>` tag.
|
|
112
|
+
|
|
113
|
+
Before the publication authorization gate, implementation must:
|
|
114
|
+
|
|
115
|
+
- select a new version greater than the currently published Triss version;
|
|
116
|
+
- update the version in root `package.json`;
|
|
117
|
+
- update the top-level and root-package version fields in `package-lock.json`;
|
|
118
|
+
- add the workspace package and its matching version to `package-lock.json` through npm, not by manual lockfile editing;
|
|
119
|
+
- set the same version in `packages/dsh-provider-bundle/package.json`;
|
|
120
|
+
- move the relevant `CHANGELOG.md` content from `Unreleased` into the dated release section and recreate an empty `Unreleased` section;
|
|
121
|
+
- describe both the companion bundle and the unchanged Triss runtime boundary in the changelog;
|
|
122
|
+
- update release workflow tests and `.github/workflows/publish.yml` so tag-to-version checks cover both manifests, both tarballs are inspected, and both npm packages publish with provenance.
|
|
123
|
+
|
|
124
|
+
The release workflow must be safely retryable when one npm publication succeeds before the other.
|
|
125
|
+
|
|
126
|
+
An already-published target version is acceptable only when registry metadata and tarball integrity match the locally verified artifact; any mismatch fails closed and requires a new version.
|
|
127
|
+
|
|
128
|
+
### Release authorization: fresh vs retry (review round 4, §1)
|
|
129
|
+
|
|
130
|
+
Because an already-used `package@version` combination can never be published
|
|
131
|
+
again, a partially published release train MUST remain completable even after
|
|
132
|
+
`main` has moved past the tag. The publish workflow therefore authorizes a
|
|
133
|
+
tag in one of two modes, decided from live registry state BEFORE any step
|
|
134
|
+
needs `id-token` permissions:
|
|
135
|
+
|
|
136
|
+
- **fresh** — neither package exists on the registry yet: the tag SHA must
|
|
137
|
+
equal the current `origin/main` SHA (a new release is only ever authorized
|
|
138
|
+
at the exact tip), and the tagged `install.sh` must match `origin/main`.
|
|
139
|
+
- **retry** — at least one package is already published with byte-identical
|
|
140
|
+
content: the tag SHA must merely be an ancestor of current `origin/main`
|
|
141
|
+
(`git merge-base --is-ancestor`), so the remaining package can be
|
|
142
|
+
published and the release completed.
|
|
143
|
+
|
|
144
|
+
`scripts/publish-gate.js authorize-tag` implements this decision as a pure,
|
|
145
|
+
unit-tested function over the `plan-publish` result plus two booleans
|
|
146
|
+
(`--exact-main`, `--ancestor-main`).
|
|
147
|
+
|
|
148
|
+
### Verified-bytes publication (review round 4, §7)
|
|
149
|
+
|
|
150
|
+
The workflow publishes exactly the bytes that were inspected by the gates:
|
|
151
|
+
the unprivileged `release-gates` job packs and hashes both tarballs, and the
|
|
152
|
+
publish job re-packs with `npm pack --ignore-scripts` (no lifecycle hooks,
|
|
153
|
+
no repository scripts, no `npm ci`) and byte-compares the SHA-256 of both
|
|
154
|
+
repacked tarballs against the gates artifact before `npm publish
|
|
155
|
+
--ignore-scripts --provenance` runs from the checked-out directories.
|
|
156
|
+
`npm pack` output is byte-deterministic, and `npm publish` packs through the
|
|
157
|
+
same code path, so the published tarball equals the inspected artifact.
|
|
158
|
+
Provenance requires publishing from a git checkout in CI, which is why the
|
|
159
|
+
publish step uses verified directories rather than the pre-packed tarball
|
|
160
|
+
files.
|
|
161
|
+
|
|
162
|
+
### Environment and required gates (review round 4, §3–4)
|
|
163
|
+
|
|
164
|
+
The tag publish workflow calls the same reusable bundle-checks workflow
|
|
165
|
+
(bundle matrix + real Harness lifecycle) as PR CI, aggregates them in a
|
|
166
|
+
`release-gates` job, and only the minimal `npm-publish` job — which runs no
|
|
167
|
+
repository scripts — holds `id-token: write` and the `npm-production`
|
|
168
|
+
environment. Owner-side settings (not expressible in this repository's
|
|
169
|
+
code) are required before the first tag: make the aggregate checks required
|
|
170
|
+
in the repository ruleset, add required reviewers to the `npm-production`
|
|
171
|
+
environment, bind the npm trusted publisher to that environment, and
|
|
172
|
+
protect `v*` tags. If the companion package does not yet exist on npm,
|
|
173
|
+
trusted publishing cannot be configured for it: a one-time bootstrap
|
|
174
|
+
publication of the exact verified tarball (followed by enabling the trusted
|
|
175
|
+
publisher and disabling token publishing) must be authorized first.
|
|
176
|
+
|
|
177
|
+
## Compatibility evidence contract
|
|
178
|
+
|
|
179
|
+
Every local tarball acceptance, CI run, and registry smoke records this tuple:
|
|
180
|
+
|
|
181
|
+
```text
|
|
182
|
+
Node version
|
|
183
|
+
pnpm version
|
|
184
|
+
@deepseek-ai/dsh version
|
|
185
|
+
@deepseek-ai/dsh-llm-pi-ai version
|
|
186
|
+
resolved @earendil-works/pi-ai version
|
|
187
|
+
resolved pi-ai package integrity from the profile lockfile
|
|
188
|
+
triss-dsh-provider-bundle version and tarball integrity
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The isolated profile smoke retains the output of `pnpm list @earendil-works/pi-ai --depth Infinity --json` and the relevant integrity entry from its lockfile.
|
|
192
|
+
|
|
193
|
+
Release evidence must not call `pi-ai` pinned merely because the adapter declares `^0.82.1`.
|
|
194
|
+
|
|
195
|
+
Provider-id and credential-reference assertions always run.
|
|
196
|
+
|
|
197
|
+
Exact model-id assertions are derived from and reported with the resolved `pi-ai` version.
|
|
198
|
+
|
|
199
|
+
If the resolved catalogue removes or renames an acceptance model, implementation selects a current model and updates evidence rather than declaring a stale local model.
|
|
200
|
+
|
|
201
|
+
Compatibility is never claimed from the Harness version alone.
|
|
202
|
+
|
|
203
|
+
## Runtime prerequisites
|
|
204
|
+
|
|
205
|
+
Normal Triss CLI installation retains its current `Node >=22` contract.
|
|
206
|
+
|
|
207
|
+
Using the companion bundle through Harness requires Node `^22.19.0 || >=24.0.0`, matching the verified Harness engine range.
|
|
208
|
+
|
|
209
|
+
Bundle CI and tarball acceptance run on at least Node `22.19.0` and Node `24`; Node `26` is included while upstream supports it.
|
|
210
|
+
|
|
211
|
+
The `dsh plugin` command forwards directly to `pnpm`, so `pnpm` must be installed and available on `PATH`.
|
|
212
|
+
|
|
213
|
+
The bundle README lists Node, pnpm, tested `dsh`, resolved `dsh-llm-pi-ai`, and resolved `pi-ai` versions before the installation command.
|
|
214
|
+
|
|
215
|
+
## Bundle contract
|
|
216
|
+
|
|
217
|
+
The bundle replaces the dormant base row's complete composition configuration:
|
|
218
|
+
|
|
219
|
+
```yaml
|
|
220
|
+
- id: llm-pi-ai
|
|
221
|
+
config:
|
|
222
|
+
providers:
|
|
223
|
+
opencode:
|
|
224
|
+
apiKeyEnv: OPENCODE_API_KEY
|
|
225
|
+
opencode-go:
|
|
226
|
+
apiKeyEnv: OPENCODE_API_KEY
|
|
227
|
+
zai:
|
|
228
|
+
apiKeyEnv: ZAI_API_KEY
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The bundle-owned composition base declares exactly `opencode`, `opencode-go`, and `zai`.
|
|
232
|
+
|
|
233
|
+
The bundle must not declare `baseURL`, `api`, models, headers, context windows, output limits, reasoning formats, or pricing.
|
|
234
|
+
|
|
235
|
+
Omitting those fields makes `dsh-llm-pi-ai` reuse each resolved catalogue provider's protocol, endpoint, model metadata, compatibility settings, and authentication support.
|
|
236
|
+
|
|
237
|
+
The bundle does not override the `agent-default-model` row.
|
|
238
|
+
|
|
239
|
+
## Configuration layering contract
|
|
240
|
+
|
|
241
|
+
Harness resolves provider profiles through schema defaults, the bundle-owned composition base, user settings, and later patch layers.
|
|
242
|
+
|
|
243
|
+
The effective runtime configuration may therefore contain additional routes or override bundle-owned fields.
|
|
244
|
+
|
|
245
|
+
A user setting may change `opencode.apiKeyEnv`, override its endpoint or models, or keep a route active after the bundle is removed.
|
|
246
|
+
|
|
247
|
+
Removing the bundle restores the dormant base posture only in a clean isolated profile with no user `llm-pi-ai` settings and no later patch that activates routes.
|
|
248
|
+
|
|
249
|
+
Removing the bundle never deletes user settings.
|
|
250
|
+
|
|
251
|
+
A provider route registered by another adapter family conflicts with the same route from this bundle and must fail loud with the upstream duplicate-adapter contract; the bundle never silently takes ownership.
|
|
252
|
+
|
|
253
|
+
## Credential and security contract
|
|
254
|
+
|
|
255
|
+
The bundle stores credential references only.
|
|
256
|
+
|
|
257
|
+
It never receives, reads, copies, logs, serializes, or publishes credential values.
|
|
258
|
+
|
|
259
|
+
Both OpenCode routes reference `OPENCODE_API_KEY`, allowing one managed Harness credential or inherited environment value to serve Zen and Go without duplication.
|
|
260
|
+
|
|
261
|
+
Direct Z.AI references `ZAI_API_KEY`, the name owned by the resolved `pi-ai` provider.
|
|
262
|
+
|
|
263
|
+
Triss uses `ZHIPU_API_KEY` for its own Z.AI integration, but the companion bundle does not copy, rename, or alias that secret.
|
|
264
|
+
|
|
265
|
+
A user who wants the same underlying credential in both products explicitly stores it under each product's expected reference.
|
|
266
|
+
|
|
267
|
+
Live tests receive only the credential required by the selected route and never retain a credential value in logs, fixtures, snapshots, package metadata, release evidence, or a Discussion.
|
|
268
|
+
|
|
269
|
+
## User contract
|
|
270
|
+
|
|
271
|
+
Installation into an existing Harness profile is:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
pnpm --version
|
|
275
|
+
node --version
|
|
276
|
+
dsh plugin --profile headless add -w triss-dsh-provider-bundle@<version>
|
|
277
|
+
dsh --profile headless --dump-config
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
`dsh plugin add` forwards to `pnpm add`, and pnpm 9 treats the Harness
|
|
281
|
+
profile directory (its `pnpm-workspace.yaml` declares `packages: [.]`) as a
|
|
282
|
+
workspace root, so the command needs `-w` — the form the lifecycle CI job
|
|
283
|
+
verifies — or `NPM_CONFIG_IGNORE_WORKSPACE_ROOT_CHECK=true` in the
|
|
284
|
+
environment. The verified tuple is dsh `0.1.0-rc.6` × pnpm `9.0.0`.
|
|
285
|
+
|
|
286
|
+
The companion package can be installed into any profile that already includes `@deepseek-ai/dsh-base`; it does not own the runner or UI layer.
|
|
287
|
+
|
|
288
|
+
The README documents these release-acceptance routes:
|
|
289
|
+
|
|
290
|
+
| Route | Credential reference | Initial acceptance model for resolved `pi-ai@0.82.1` |
|
|
291
|
+
| --- | --- | --- |
|
|
292
|
+
| `opencode` | `OPENCODE_API_KEY` | `nemotron-3-ultra-free` (free tier; the paid `deepseek-v4-flash` is balance-blocked on the acceptance workspace — see the acceptance status) |
|
|
293
|
+
| `opencode-go` | `OPENCODE_API_KEY` | `deepseek-v4-flash`, `glm-5.2` |
|
|
294
|
+
| `zai` | `ZAI_API_KEY` | `glm-5.2` |
|
|
295
|
+
|
|
296
|
+
The table is release evidence, not a package-owned static catalogue.
|
|
297
|
+
|
|
298
|
+
Model availability, billing, quota, regional hosting, and provider policy remain service-owned runtime facts.
|
|
299
|
+
|
|
300
|
+
An HTTP 401, 403, 429, billing rejection, free-usage limit, or regional-opt-in response is surfaced without mutating configuration or falling back to a different route.
|
|
301
|
+
|
|
302
|
+
## Keyless package and composition tests
|
|
303
|
+
|
|
304
|
+
### Package contract
|
|
305
|
+
|
|
306
|
+
Focused tests prove:
|
|
307
|
+
|
|
308
|
+
- the companion owns a distinct package name and the root tarball contains neither its manifest nor patch;
|
|
309
|
+
- the package manifest resolves `cordis.patch.yml` from the packed tarball;
|
|
310
|
+
- the public file allowlist contains only the manifest plus `cordis.patch.yml`, README, and license;
|
|
311
|
+
- the companion has no executable lifecycle hooks or undeclared dependency closure;
|
|
312
|
+
- its Node engine matches the verified Harness range;
|
|
313
|
+
- the bundle patch declares only the three intended catalogue profiles and credential references;
|
|
314
|
+
- forbidden duplicated provider fields are absent;
|
|
315
|
+
- installation does not change the Harness default provider or model.
|
|
316
|
+
|
|
317
|
+
### Package-resolution isolation matrix
|
|
318
|
+
|
|
319
|
+
End-to-end fixtures exercise both globally installed and `npx`-style Harness layouts with:
|
|
320
|
+
|
|
321
|
+
1. no global `triss-coworker` installation;
|
|
322
|
+
2. an older global Triss without `dsh.bundle`;
|
|
323
|
+
3. an older global Triss carrying a deliberately different bundle patch;
|
|
324
|
+
4. a newer global Triss than the profile companion;
|
|
325
|
+
5. companion installation into a new profile;
|
|
326
|
+
6. companion update between two fixture versions with different non-secret marker metadata;
|
|
327
|
+
7. companion removal;
|
|
328
|
+
8. companion reinstallation.
|
|
329
|
+
|
|
330
|
+
Every case asserts that Harness resolves `triss-dsh-provider-bundle` from the profile's `node_modules`, never from a `triss-coworker` package at the installation anchor.
|
|
331
|
+
|
|
332
|
+
The update case must change the effective companion patch, and removal must delete the companion from `dsh.profile.bundles`.
|
|
333
|
+
|
|
334
|
+
### Settings-layer matrix
|
|
335
|
+
|
|
336
|
+
Composition tests cover:
|
|
337
|
+
|
|
338
|
+
1. a clean profile, where the bundle base activates the three routes;
|
|
339
|
+
2. user settings that add a fourth provider, which remains present beside the three base routes;
|
|
340
|
+
3. user settings that override `opencode.apiKeyEnv`, which win in the effective configuration;
|
|
341
|
+
4. bundle removal with retained user settings, which preserves user-owned routes and values;
|
|
342
|
+
5. bundle reinstallation, which restores the composition base without deleting user overrides;
|
|
343
|
+
6. a route collision with another adapter family, which fails loud with the duplicate-adapter error;
|
|
344
|
+
7. clean-profile removal, which alone restores the dormant `llm-pi-ai` posture.
|
|
345
|
+
|
|
346
|
+
## Live and tool-use acceptance
|
|
347
|
+
|
|
348
|
+
Every live request explicitly names its provider and model and captures session or event evidence proving the resolved pair.
|
|
349
|
+
|
|
350
|
+
Before publishing, the configured acceptance account must complete successful minimal text requests through:
|
|
351
|
+
|
|
352
|
+
- `opencode/deepseek-v4-flash`;
|
|
353
|
+
- `opencode-go/deepseek-v4-flash`;
|
|
354
|
+
- `opencode-go/glm-5.2`;
|
|
355
|
+
- `zai/glm-5.2`.
|
|
356
|
+
|
|
357
|
+
If the resolved catalogue changes, the exact replacements are selected from that catalogue and recorded with the compatibility tuple.
|
|
358
|
+
|
|
359
|
+
An entitlement or billing failure proves error propagation but does not satisfy successful live acceptance.
|
|
360
|
+
|
|
361
|
+
Coding-tool acceptance runs two disposable tasks with explicit routing:
|
|
362
|
+
|
|
363
|
+
1. provider `opencode-go`, model `deepseek-v4-flash`;
|
|
364
|
+
2. provider `opencode-go`, model `glm-5.2`.
|
|
365
|
+
|
|
366
|
+
Each task must produce captured evidence containing the selected provider and model, at least one tool call, the matching tool result, and the expected disposable file diff.
|
|
367
|
+
|
|
368
|
+
A successful final diff without route and tool-event evidence is a failed acceptance test.
|
|
369
|
+
|
|
370
|
+
No live test may silently retry through `deepseek-official` or another provider.
|
|
371
|
+
|
|
372
|
+
### Acceptance status (pre-release, 2026-08-15)
|
|
373
|
+
|
|
374
|
+
Recorded honestly rather than rounded up to green:
|
|
375
|
+
|
|
376
|
+
- `opencode` route — SATISFIED (2026-08-15, late evening) via an
|
|
377
|
+
owner-approved catalogue substitution: `opencode/nemotron-3-ultra-free`
|
|
378
|
+
completed a successful minimal text request ("pong") through the bundle
|
|
379
|
+
profile (dump-config proves provider `opencode` + model
|
|
380
|
+
`nemotron-3-ultra-free`; resolved `pi-ai@0.82.1`). A second free-tier
|
|
381
|
+
model, `laguna-s-2.1-free`, also returned a successful response. The
|
|
382
|
+
original paid `deepseek-v4-flash` stays 401 `CreditsError` on this Zen
|
|
383
|
+
workspace (insufficient balance — an account fact, not a code defect),
|
|
384
|
+
and some free catalogue entries are not enabled for the workspace
|
|
385
|
+
(`ling-3.0-flash-free`, `north-mini-code-free` → 401 `ModelError`);
|
|
386
|
+
`deepseek-v4-flash-free` and `mimo-v2.5-free` returned 429 under their
|
|
387
|
+
per-model free quotas. Credential: the account's only key (opencode CLI
|
|
388
|
+
auth; `gai1.opencode.env` holds the same value).
|
|
389
|
+
- `opencode-go/deepseek-v4-flash` — passed (text and coding-tool);
|
|
390
|
+
- `opencode-go/glm-5.2` — passed (text and coding-tool);
|
|
391
|
+
- `zai/glm-5.2` — passed.
|
|
392
|
+
|
|
393
|
+
All four text routes and both coding-tool cases are green. Live acceptance
|
|
394
|
+
is complete; publishing is now gated only on the explicit tag/publication
|
|
395
|
+
authorization (plan step 15) and the owner-side release prerequisites.
|
|
396
|
+
|
|
397
|
+
The registry smokes recorded alongside this status ran against a local
|
|
398
|
+
`npm pack` tarball (byte-identical to the future registry artifact) BEFORE
|
|
399
|
+
publication. They are pre-release evidence, not the post-publication
|
|
400
|
+
registry install that a complete step 16 requires. The publish workflow's
|
|
401
|
+
`registry-acceptance` job covers the automatable half of step 16 after
|
|
402
|
+
publication: install the registry companion into fresh profiles on Node
|
|
403
|
+
`22.19.0` and `24`, verify add/remove/reinstall through `dsh plugin`, assert
|
|
404
|
+
the three routes by PARSING the dumped `llm-pi-ai.config.providers` object
|
|
405
|
+
(exact provider set and `apiKeyEnv` mapping — substring greps accepted
|
|
406
|
+
partial configurations, review round 4 §2), byte-verify both published
|
|
407
|
+
packages against the gates artifact, and record the full compatibility
|
|
408
|
+
tuple plus registry integrity and provenance attestations as an evidence
|
|
409
|
+
artifact. The evidence step is FAIL-CLOSED: every tuple field is required
|
|
410
|
+
(the job dies on any missing value), the profile `pnpm list --depth
|
|
411
|
+
Infinity --json` output and the profile `pnpm-lock.yaml` are uploaded as
|
|
412
|
+
artifacts, and the companion's integrity is taken from that lockfile. The
|
|
413
|
+
adapters (`dsh-llm-pi-ai`, resolved `pi-ai`) resolve from the running dsh
|
|
414
|
+
INSTALLATION, not from profile dependencies (verified live: the profile
|
|
415
|
+
carries only the companion and the template bundles) — their versions are
|
|
416
|
+
recorded from the installation and the resolved `pi-ai`'s registry
|
|
417
|
+
integrity for that exact version is recorded alongside. Provenance is
|
|
418
|
+
verified rather than assumed: attestations are read from
|
|
419
|
+
`dist.attestations` (where npm/pacote store them) and additionally checked
|
|
420
|
+
cryptographically by installing the exact released version into a throwaway
|
|
421
|
+
project and running `npm audit signatures --json --include-attestations`
|
|
422
|
+
(the companion must show verified statuses with nothing invalid or
|
|
423
|
+
missing). The registry UPDATE path runs whenever a previous registry version
|
|
424
|
+
exists (install previous, then update in place to the exact released
|
|
425
|
+
version); for the FIRST release of the companion no previous version can
|
|
426
|
+
exist, and update mechanics are guaranteed by the real-Harness lifecycle
|
|
427
|
+
job's in-place v1→v2 proof — an explicit amendment of this contract. Live
|
|
428
|
+
provider-model smokes on the published package remain credential-bound
|
|
429
|
+
recorded acceptance evidence and are not part of CI.
|
|
430
|
+
|
|
431
|
+
## Community ecosystem proposal
|
|
432
|
+
|
|
433
|
+
The bundle is published and documented as an independently maintained community plugin, not as a temporary copy awaiting an official package.
|
|
434
|
+
|
|
435
|
+
After registry acceptance, and only with explicit authorization, create a GitHub Discussion that includes:
|
|
436
|
+
|
|
437
|
+
- the configuration gap and why a transport adapter is unnecessary;
|
|
438
|
+
- the three provider profiles and credential references;
|
|
439
|
+
- the package-resolution, layering, and live acceptance evidence;
|
|
440
|
+
- the published package and repository link;
|
|
441
|
+
- the compatibility tuple;
|
|
442
|
+
- a question asking whether maintainers want an official provider-preset bundle or prefer the ecosystem package to remain external.
|
|
443
|
+
|
|
444
|
+
Associate the Triss repository with the `dsh-plugin` topic after separate authorization.
|
|
445
|
+
|
|
446
|
+
Do not prepare an upstream branch, Agent Note, bilingual upstream documentation, repository tests, or pull request while `CONTRIBUTING.md` rejects external PRs.
|
|
447
|
+
|
|
448
|
+
A future upstream implementation begins only after a direct maintainer invitation or a verified policy change and follows the then-current repository instructions rather than this snapshot.
|
|
449
|
+
|
|
450
|
+
## Implementation sequence
|
|
451
|
+
|
|
452
|
+
1. Re-verify current Harness contribution policy, engine range, plugin resolution, `dsh-llm-pi-ai` dependency range, and resolved catalogue.
|
|
453
|
+
2. Re-check npm availability for `triss-dsh-provider-bundle`; stop before implementation if the name is no longer available.
|
|
454
|
+
3. Add RED tests for package identity, workspace metadata, public files, lifecycle-hook absence, patch shape, route ids, credentials, default preservation, and forbidden duplicated fields.
|
|
455
|
+
4. Add RED package-resolution fixtures for every global-Triss, install, update, remove, and reinstall scenario.
|
|
456
|
+
5. Add RED composition fixtures for clean, added-provider, overridden-key, retained-settings removal, reinstall, duplicate-adapter, and clean removal behavior.
|
|
457
|
+
6. Add the minimal workspace package, patch, README, and license needed to make those tests pass without changing Triss runtime code.
|
|
458
|
+
7. Update release-gate tests and workflows to version, pack, inspect, provenance-publish, retry, and registry-verify both package identities from one tag.
|
|
459
|
+
8. Add the dedicated Node `22.19.0`, `24`, and `26` bundle matrix and verify `pnpm`-missing diagnostics separately.
|
|
460
|
+
9. Run focused tests, the complete root Triss suite, lint, `git diff --check`, workspace lockfile validation, and packed-tarball inspection.
|
|
461
|
+
10. Install the packed companion into isolated global and `npx`-style Harness fixtures and run the package-resolution and settings-layer matrices.
|
|
462
|
+
11. Record the complete dependency and integrity tuple from each accepted tarball installation.
|
|
463
|
+
12. Run all four explicit text-route smokes and both explicit coding-tool smokes, retaining only redacted route, model, tool-event, and result evidence.
|
|
464
|
+
13. Select the release version, update both manifests and generated lockfile fields, move the changelog entry out of `Unreleased`, and rerun every release and tarball gate.
|
|
465
|
+
14. Review the final diff and both tarballs for secrets, unrelated files, generated debris, root-package contamination, and any Triss runtime integration.
|
|
466
|
+
15. Ask for explicit authorization to create the coordinated version tag and publish both npm packages.
|
|
467
|
+
16. After publication, install the registry companion into fresh isolated profiles on Node `22.19.0` and `24`, verify install/update/remove, and repeat all three provider-route families with explicit model evidence.
|
|
468
|
+
17. Ask separately for authorization to add the `dsh-plugin` topic and publish the maintainer Discussion.
|
|
469
|
+
|
|
470
|
+
The coordinated npm release and ecosystem proposal are separate external actions and require separate approval.
|
|
471
|
+
|
|
472
|
+
## Deferred Triss integration
|
|
473
|
+
|
|
474
|
+
This plan adds no Triss runtime or coder-engine support.
|
|
475
|
+
|
|
476
|
+
The following surfaces remain unchanged during bundle implementation and publication:
|
|
477
|
+
|
|
478
|
+
- `src/coder.js` and all coder engine/provider routing;
|
|
479
|
+
- CLI commands, help, completion, status, and config wizard behavior;
|
|
480
|
+
- MCP tool schemas and descriptions;
|
|
481
|
+
- agent instruction templates and `triss init` output;
|
|
482
|
+
- `TRISS_CODER_*`, worker, OpenCode, and Z.AI environment contracts;
|
|
483
|
+
- the root `triss-coworker` published-file allowlist and runtime dependency graph.
|
|
484
|
+
|
|
485
|
+
A later Triss integration plan begins only when:
|
|
486
|
+
|
|
487
|
+
1. the companion package is publicly installable and registry-verified;
|
|
488
|
+
2. its packed contents and installation path are stable;
|
|
489
|
+
3. fresh profiles pass all required provider and tool-use smokes;
|
|
490
|
+
4. Harness invocation satisfies Triss deny-first command policy, credential isolation, non-interactive execution, output capture, cancellation, and worktree rules;
|
|
491
|
+
5. the user explicitly authorizes integration work.
|
|
492
|
+
|
|
493
|
+
That later plan decides whether Harness becomes a new coder engine, a user-managed external engine, or a documented manual option.
|
|
494
|
+
|
|
495
|
+
## Acceptance criteria
|
|
496
|
+
|
|
497
|
+
- The bundle publishes as `triss-dsh-provider-bundle`, not as part of `triss-coworker`.
|
|
498
|
+
- Both packages live in the Triss repository, share the selected version and tag, and have independently inspected tarballs.
|
|
499
|
+
- Global or `npx` Triss installations at older, newer, bundle-less, and different-patch versions cannot change which companion package the Harness profile resolves.
|
|
500
|
+
- Install, update, remove, and reinstall behavior is verified through `dsh plugin` with `pnpm` on `PATH`.
|
|
501
|
+
- The bundle-owned composition base declares exactly `opencode`, `opencode-go`, and `zai`; effective settings may add or override routes.
|
|
502
|
+
- Clean, overridden, additive, retained-settings removal, reinstall, clean removal, and adapter-conflict fixtures have explicit expected outcomes.
|
|
503
|
+
- OpenCode Zen and Go base profiles use `OPENCODE_API_KEY`; direct Z.AI uses `ZAI_API_KEY`.
|
|
504
|
+
- No secret copying or `ZHIPU_API_KEY` aliasing occurs.
|
|
505
|
+
- Installing the bundle does not change the Harness default provider or model.
|
|
506
|
+
- Compatibility evidence records exact Node, pnpm, Harness, adapter, resolved `pi-ai`, lockfile integrity, package version, and tarball integrity facts.
|
|
507
|
+
- Exact model assertions are tied to the recorded resolved catalogue.
|
|
508
|
+
- Successful live text acceptance explicitly proves `opencode`, `opencode-go`, and `zai` routes with captured provider/model evidence.
|
|
509
|
+
- Coding-tool acceptance explicitly proves `opencode-go/deepseek-v4-flash` and `opencode-go/glm-5.2`, including tool call, tool result, provider/model evidence, and expected file diff.
|
|
510
|
+
- Bundle validation passes on Node `22.19.0`, `24`, and `26`; normal Triss retains `Node >=22`.
|
|
511
|
+
- The README requires `pnpm` on `PATH` and reports the tested compatibility tuple.
|
|
512
|
+
- Root and companion manifest versions, generated lockfile versions, tag, and changelog release section agree before publication authorization.
|
|
513
|
+
- Release gates pack, inspect, publish, and registry-verify both packages with provenance and safe retry semantics.
|
|
514
|
+
- The root Triss tarball contains no companion manifest or patch, and Triss runtime tests remain green without Harness integration.
|
|
515
|
+
- The community package is presented as an independent ecosystem plugin.
|
|
516
|
+
- No upstream PR artifacts are required or created while upstream rejects external PRs.
|
|
517
|
+
- Neither npm publication nor the Discussion/topic write occurs without explicit authorization.
|
|
518
|
+
|
|
519
|
+
## Validation for this planning change
|
|
520
|
+
|
|
521
|
+
This document-only correction requires:
|
|
522
|
+
|
|
523
|
+
```bash
|
|
524
|
+
git diff --check
|
|
525
|
+
git status --short --branch
|
|
526
|
+
git diff -- docs/deepseek-harness-provider-bundle-plan.md
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
No package, source, workflow, lockfile, changelog, or runtime configuration change belongs in the planning commit.
|