CodeNomad/scripts/test-output-limit-native.mjs
Pascal André 8e8ca15934
chore(opencode): qualify runtime 2.0.29 and align client/plugin pins (#948)
## Summary

- Recommend and pin OpenCode **2.0.29** (`@opencode/client`,
`@opencode/plugin`); the technical minimum stays **2.0.27** since
2.0.28/2.0.29 keep Effect 4.0.1.
- Add 2.0.29 as a reviewed contract profile beside 2.0.27; 2.0.28 and
future/custom labels keep authenticated negotiation.
- Test fixture only: the recurring Missions host declares the
`credential` domain that the 2.0.29 Promise adapter reads eagerly (the
managed owner spreads `ctx`, dropping the Proxy fallback). No product
code change.
- Two new isolated fixtures for upstream behavior changes: bounded
output-length continuation, and rejected Promise tools / native denial.
- Compatibility docs, CONTRIBUTING, AGENTS and architecture guide
updated.

## Upstream review

- OpenAPI: same 118 paths; additive schema changes (config `policies`,
provider/model `compatibility`, `encoding`).
- Private LocationServiceMap/Form/Permission/queue contracts used by the
pending snapshot: unchanged.
- Effect stays 4.0.1.

## Validation (Windows, isolated CLIs/databases, never the shared
daemon)

- 2.0.29: plugin runtime, automation, pruning/history/proxy, Missions
contract/family control/full journey, session environment, fork, aside,
prompt skills, Git degraded/init, provider usage/accounts, temporary
workspaces, blank-session cleanup, output-limit continuation, Promise
tool failure, system settings discovery, native upgrade 2.0.15→2.0.29.
- 2.0.27 (minimum): plugin runtime, automation, pruning, Missions
contract/family, session environment, fork, aside, prompt skills, blank
cleanup.
- Server: 2235 passed / 7 skipped / 0 failed. UI: 1524 passed. Tauri
crate 268/268, updater handoff 1/1, UI updater flow 13/13 (dev base
includes #786).

## Known, not caused by this change

`scripts/test-permission-receipts-native.mjs` times out identically on
2.0.27 with the previous pins; tracked separately.
2026-10-14 15:06:35 +02:00

34 lines
2.1 KiB
JavaScript

// Real isolated runtime and loopback provider; exercise the native bounded continuation policy.
import assert from "node:assert/strict"
import { mkdir, writeFile } from "node:fs/promises"
import path from "node:path"
import { withProductRuntime } from "./native-product-fixture.mjs"
await withProductRuntime(process.argv[2], async ({ root }) => {
const plugin = path.join(root, "output-limit-fixture")
await mkdir(plugin)
await writeFile(path.join(plugin, "index.ts"), `export default { id: "output-limit-fixture", async setup(ctx) {
await ctx.session.hook("http.response", async event => {
if (event.kind !== "primary") return
const text = await event.response.text()
event.response = new Response(text.replaceAll('"finish_reason":"stop"', '"finish_reason":"length"'), {
status: event.response.status, headers: { "content-type": "text/event-stream" },
})
})
} }`)
return { plugins: [plugin] }
}, async ({ client, root }) => {
const session = await client.session.create({ location: { directory: root } })
await client.session.prompt({ sessionID: session.id, text: "Return only the synthetic fixture answer." })
await client.session.wait({ sessionID: session.id })
const messages = (await client.message.list({ sessionID: session.id, order: "asc", limit: 100 })).data
const assistants = messages.filter(message => message.type === "assistant")
assert.equal(assistants.length, 3, "Native continuation must stop after two output-limit continuations")
assert(assistants.every(message => message.finish === "length"))
assert.equal(messages.filter(message => message.type === "user").length, 1, "The user prompt must not be replayed")
const idle = messages.filter(message => message.type === "idle").at(-1)
assert.equal(idle?.outcome, "failed", "Exhausted continuation must become a durable native failure")
const state = (await client.session.active())[session.id]
assert.equal(state, undefined, "Output-limit failure must not leave the session active")
console.log("PASS: native length recovery is bounded, preserves a single user prompt and settles failed/idle")
})