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.