* refactor(llm-deepseek): share the /models listing machinery
Move the account route's `/models` request and decoding, its
credential-scoped listing cache, and listed-catalog resolution with the
version gate into the shared DeepSeek Messages library, so a second
route can follow the same listing. Names drop the account prefix, the
cache takes each access's endpoint settings with the call, and it gains
`invalidate()` for a forced reload. `isBuiltInCatalog()` recognizes the
catalog an uncustomized `models` setting resolves to.
The account route keeps its behavior; only its imports and the
override diagnostic wording ("model listing") change.
* feat(llm-deepseek-api-key): follow the official /models listing
While `models` equals the built-in catalog and the Messages origin is
https://api.deepseek.com, `deepseek-official` serves the official
`GET /models` listing, authenticated with the API key in `x-api-key`.
Loading, refresh, fallback, merging, and the client-version gate match
the account route: the first access waits up to `modelsTimeoutMs`, a
listing older than `modelsMaxAgeMs` refreshes in the background on the
next access, a failure keeps the last good listing or the built-in
catalog, and listed models this build cannot serve are refused before
network I/O.
A customized `models` list replaces the catalog and requests nothing.
Switching between a customized catalog and the listing discards the
cached listing, so Restore defaults reloads it on the next access.
Suites that boot the route on the official endpoint now answer the
listing themselves instead of reaching the network.
* docs: describe the official route model listing
Document when `deepseek-official` follows the official `/models`
listing, its timing fields, customization precedence, and the forced
reload after Restore defaults in the API-key README, the shared
transport README, and the provider guide. Record the decision in a new
Agent Note, keep the account note's statement of where the shared
listing code lives current, and regenerate the configuration catalog.
* test(llm-deepseek-api-key): pin the once-per-listing hidden-entry diagnostic
* docs: regenerate module and event graphs for the shared listing
* fix(llm-deepseek-api-key): report credential failures on the model request
On the official endpoint, `connect` waited for the listing view, whose
credential lookup rethrew a malformed key or a credential-store failure
before the agent loop recorded the prompt. A failed lookup now resolves
the connection from the current listing view, so `resolveAuth` reports
the failure on the model request and the turn keeps the prompt and the
failed attempt. A caller abort still rejects.
* docs(llm-deepseek-api-key): name which hidden listing entries are logged
* test: keep unit suites off the official model listing
Suites that boot the DeepSeek routes with a dummy or inherited key now
request `GET https://api.deepseek.com/models` on the official endpoint.
A unit-lane setup file rejects that request at once, so such a suite
serves the built-in catalog instead of reaching production or waiting
out the listing deadline on a network that never answers; suites that
exercise the listing answer `fetch` themselves. Other requests pass
through unchanged.
* feat(llm-deepseek): read tool_update from the model listing
Both DeepSeek routes now take a listed model's Messages tool update mode
from `api_capabilities.anthropic_messages.tool_update`, alongside the
system prompt mode. `in-history` and `addition-only` replace the
bundled mode; any other value reads as `leading-only` and removes it.
An absent or `null` mode keeps the bundled one, so a listing that does
not declare the field leaves `deepseek-flash` on `addition-only`.
`system_prompt_update: null` likewise keeps the bundled mode now; it
previously read as `leading-only`, which a serializer writing empty
values as null would have turned into a cache-unfriendly downgrade.
* fix(llm-deepseek): sync the built-in context window with the official listing
The official `/models` listing declares a 1,048,576-token context window
for `deepseek-flash` and `deepseek-v4-pro`; the built-in catalog said
1,000,000, a decimal-versus-binary mismatch. Both built-in entries now
carry the listed value, so offline starts and listing failures size the
context the same way the listing does. The Models page shows the exact
count for these rows, since 1,048,576 has no decimal K/M spelling.
`defaultContextWindow`, the fallback for model ids the catalog does not
describe, stays 1,000,000.
* test(llm-deepseek-api-key): reject the stubbed listing request with an Error
* test(cli): keep the built SDK smoke off the official model listing
The SDK profile's initialize now resolves the deepseek-official catalog,
which requests GET https://api.deepseek.com/models on the official
endpoint. With the smoke's fixture key that request answers 401 and the
route warns on stderr, so the test's empty-stderr assertion failed in the
e2e and snapshots lanes. Point the run at a loopback mock and assert it
received no model call.
* test(llm-deepseek): compose the malformed-key turn without the native executor
release/dsh-0.2.1 predates @deepseek-ai/dsh-tool-executor-native; its tool
runtime executes tools itself. Compose the official-route turn the way
account-routing.spec.ts does on this branch.
* fix(llm-deepseek-api-key): gate nothing when the credential lookup fails
The listing cache switches scope only after it reads a credential, so a
failed lookup left `connect` serving the previous credential's listing.
After a key whose listing refuses a model was replaced by a malformed one,
`admit` refused that model with CLIENT_UPGRADE_REQUIRED before the turn
recorded the prompt, instead of `resolveAuth` reporting the credential
error on the request. Serve the built-in catalog without listing gates
when the lookup fails.
* test(llm-deepseek-api-key): pin the once-per-listing diagnostic across request preparation
The hidden-entry diagnostic test repeated the same discovery assertion to
prove a second pass reports nothing new, which read as a duplicate. Assert
the single warning after the request preparations instead; they resolve
the same listing, so dropping the per-listing deduplication still fails
the test.
* docs(llm-deepseek-api-key): note that a list matching an earlier built-in catalog counts as customized
Customization is judged against the running version's built-in catalog,
so a saved `models` list equal to an earlier version's catalog stops
following the listing once the built-in catalog changes, until Restore
defaults. Record the consequence in the Agent Note and the README's known
limitations.
413 lines
23 KiB
TypeScript
413 lines
23 KiB
TypeScript
import { spawnSync } from 'node:child_process'
|
|
import { fileURLToPath } from 'node:url'
|
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
|
import { resolvePwshPath } from './packages/shell/pwsh-local/src/resolve.ts'
|
|
import { defineConfig } from 'vitest/config'
|
|
import { standardDecoratorPlugin, vitestExecArgv } from './vitest.shared.ts'
|
|
import { COVERAGE_EXEMPT_ENV, coverageExemptHeavySuites } from './scripts/coverage-exempt.ts'
|
|
import { COVERAGE_PARTITION_MODE_ENV, COVERAGE_TEST_TIMEOUT_ENV, coverageTestTimeoutOptions } from './scripts/coverage-partitions.ts'
|
|
import { LOCAL_TEST_PARALLELISM_CAP, defaultParallelism } from './scripts/parallelism.ts'
|
|
|
|
// Prints exact `path:line:col` records for every uncovered statement, branch
|
|
// path, and function when a file misses the per-file 100% gate — the built-in
|
|
// threshold ERRORs name only the file. Absolute path because istanbul-reports
|
|
// require()s custom reporters (which is also why the reporter is CJS).
|
|
const uncoveredLocationsReporter = fileURLToPath(new URL('./scripts/coverage-uncovered-locations.cjs', import.meta.url))
|
|
|
|
// Resolution facade shared by every plugin instance below: tsconfig.base.json
|
|
// has no include, which vite-tsconfig-paths treats as match-all, so its paths
|
|
// map applies to every test file. paths must win over package exports so built
|
|
// lib/ never loads a second module-singleton copy.
|
|
const pathsPlugin = (): ReturnType<typeof tsconfigPaths> => tsconfigPaths({ projects: ['./tsconfig.base.json'] })
|
|
|
|
const windowsUnsupportedPackages = process.platform === 'win32'
|
|
? [
|
|
// Bash-requiring suites (a real POSIX shell is unavailable on Windows).
|
|
// The pwsh-requiring suites (pwsh-local, tool-pwsh) deliberately stay
|
|
// INCLUDED: PowerShell ships with Windows, so they run natively here.
|
|
// This explicit list (not a 'packages/shell/*' glob) keeps
|
|
// packages/shell/shell — the Service Definition package — running on Windows.
|
|
'packages/shell/bash-local',
|
|
'packages/shell/bash-sandbox',
|
|
'packages/shell/tool-bash',
|
|
'packages/experimental/hook-protocol',
|
|
'packages/experimental/hooks-claude-code',
|
|
'packages/experimental/hooks-codex',
|
|
'packages/terminal/terminal-bash',
|
|
'packages/experimental/ptc-runtime-python',
|
|
'packages/sandbox/sandbox-local',
|
|
// OpenSSH multiplexing and Unix-socket helper streams require POSIX endpoints.
|
|
'packages/ssh/*',
|
|
]
|
|
: []
|
|
|
|
const windowsUnsupportedTests = process.platform === 'win32'
|
|
? [
|
|
...windowsUnsupportedPackages.map(path => `${path}/tests/**/*.spec.ts`),
|
|
'packages/subprocess/subprocess/tests/**/*.spec.ts',
|
|
'packages/subprocess/subprocess-local/tests/local.spec.ts',
|
|
'packages/subprocess/subprocess-local/tests/process-inspector.spec.ts',
|
|
'packages/subprocess/subprocess-local/tests/spawn.spec.ts',
|
|
'packages/subprocess/subprocess-local/tests/terminal.spec.ts',
|
|
// Oracle-diff suites: they compare the worker's POSIX path/url faces
|
|
// against the host Node's own answers, which are win32 semantics on
|
|
// Windows. The worker always speaks POSIX; the Linux lanes hold the diff.
|
|
'packages/experimental/webworker-runtime/tests/node/path-diff.spec.ts',
|
|
'packages/experimental/webworker-runtime/tests/node/shim-diff.spec.ts',
|
|
// The subprocess ladder over the worker's child_process face: its kill
|
|
// rung reaches the in-worker process table through `process.kill`,
|
|
// which the ladder's win32 branch replaces with taskkill-by-real-pid —
|
|
// undeliverable to a table pid. The worker host always reports 'linux',
|
|
// so the Linux lanes hold the ladder.
|
|
'packages/experimental/webworker-runtime/tests/node/child-process.spec.ts',
|
|
]
|
|
: []
|
|
|
|
// These suites compare against or assemble the Worker's fixed Linux platform.
|
|
// Host-native Windows and macOS behavior is not their oracle.
|
|
const nonLinuxWebWorkerTests = process.platform === 'linux'
|
|
? []
|
|
: [
|
|
'packages/experimental/webworker-runtime/tests/node/fs-watch-stream.spec.ts',
|
|
'packages/experimental/webworker-runtime/tests/node/sandbox-stack.spec.ts',
|
|
]
|
|
|
|
const platformUnsupportedTests = [...windowsUnsupportedTests, ...nonLinuxWebWorkerTests]
|
|
|
|
const windowsUnsupportedCoveragePackages = process.platform === 'win32'
|
|
? [...windowsUnsupportedPackages, 'packages/subprocess/*']
|
|
: []
|
|
|
|
// Windows-only packages: their sources execute exclusively on win32 (koffi
|
|
// loads Win32 libraries), so the Linux coverage lane can never cover them.
|
|
// The Windows dev/CI lane exercises them through the probe/runner suites; the
|
|
// per-file 100% gate must not fail on their Linux-uncovered paths.
|
|
const windowsOnlyCoverageExclusions = process.platform !== 'win32'
|
|
? [
|
|
'packages/sandbox/sandbox-windows-acl/src/**/*.ts',
|
|
// The koffi-backed Win32 table (Toolhelp32/GetProcessTimes/taskkill)
|
|
// executes only on win32; its decision logic is unit-pinned on every
|
|
// host through the injected-internals suites.
|
|
'packages/subprocess/subprocess-local/src/windows-inspector.ts',
|
|
]
|
|
: []
|
|
|
|
// The confinement runner entry executes exclusively as a spawned child
|
|
// process (the sandbox seam's argv-prefix wrapper): its module-level main()
|
|
// would run the confinement in-process if imported, and vitest's v8 coverage
|
|
// never measures child processes. Its behavior is pinned end-to-end by
|
|
// tests/runner.spec.ts, which spawns the real entry through tsx.
|
|
const windowsRunnerCoverageExclusions = process.platform === 'win32'
|
|
? [
|
|
'packages/sandbox/sandbox-windows-acl/src/runner.ts',
|
|
// The session write lock's POSIX face (fs-ext flock plus inode
|
|
// verification) executes only off-Windows: the Linux lanes hold its
|
|
// per-file 100%, while the Windows branch is unit-pinned by
|
|
// win32.spec's injected bindings and exercised natively by every
|
|
// Windows suite through the real backend.
|
|
'packages/session/session-persistence-jsonl/src/lease.ts',
|
|
// The macOS provider transport uses Unix sockets; POSIX lanes cover its real socket lifecycle.
|
|
'packages/experimental/cua-macos/src/shared-native.ts',
|
|
]
|
|
: []
|
|
|
|
// pwsh-local's run/start/lifecycle suites self-skip without a real pwsh
|
|
// (executor.spec.ts hasPwsh), leaving this file
|
|
// far below per-file 100% on pwsh-less hosts; the exemption keeps those hosts
|
|
// green while CI runners ship pwsh and still enforce the full bar. The probe
|
|
// runs the suites' own resolution (the dependency-free resolve.ts module),
|
|
// so the exemption is active exactly when the suites skip — a mismatched
|
|
// narrower probe could exempt the file on hosts whose suites actually run.
|
|
const pwshCoverageExclusions = spawnSync(resolvePwshPath(), ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', '$true'], { encoding: 'utf8' }).status === 0
|
|
? []
|
|
: [
|
|
'packages/shell/pwsh-local/src/index.ts',
|
|
'packages/shell/pwsh-sandbox/src/**/*.ts',
|
|
]
|
|
|
|
const testIncludes = [
|
|
'packages/*/*/tests/**/*.spec.{ts,tsx}',
|
|
'apps/*/tests/**/*.spec.{ts,tsx}',
|
|
'scripts/**/*.spec.ts',
|
|
'website/tests/**/*.spec.ts',
|
|
]
|
|
|
|
// The instrumented coverage gate sets this env; the exempt heavy suites then
|
|
// run beside it uninstrumented (membership contract in scripts/coverage-exempt.ts).
|
|
// A set-but-not-'1' value is a misconfiguration, not a silent no-op.
|
|
const coverageExemptRaw = process.env[COVERAGE_EXEMPT_ENV]
|
|
if (coverageExemptRaw !== undefined && coverageExemptRaw !== '' && coverageExemptRaw !== '1') {
|
|
throw new Error(`vitest config: ${COVERAGE_EXEMPT_ENV} must be '1' or unset, got ${JSON.stringify(coverageExemptRaw)}.`)
|
|
}
|
|
const coverageExemptExcludes = coverageExemptRaw === '1'
|
|
? coverageExemptHeavySuites.map(suite => suite.exclude)
|
|
: []
|
|
|
|
const coveragePartitionRaw = process.env[COVERAGE_PARTITION_MODE_ENV]
|
|
if (coveragePartitionRaw !== undefined && coveragePartitionRaw !== '' && coveragePartitionRaw !== '1') {
|
|
throw new Error(`vitest config: ${COVERAGE_PARTITION_MODE_ENV} must be '1' or unset, got ${JSON.stringify(coveragePartitionRaw)}.`)
|
|
}
|
|
const coveragePartitionMode = coveragePartitionRaw === '1'
|
|
|
|
// Lanes on shared hosts raise the per-test, hook, and expect.poll defaults
|
|
// together through DSH_COVERAGE_TEST_TIMEOUT_MS; it lands in each inline
|
|
// project below because CLI flags do not reach them (coverageTestTimeoutOptions
|
|
// owns the rule and its reach).
|
|
const laneTestBudget = coverageTestTimeoutOptions(process.env[COVERAGE_TEST_TIMEOUT_ENV])
|
|
// Outside CI, forks follow the local worker budget; CI keeps Vitest's own default for its runner.
|
|
const localWorkerBudget = process.env.CI === 'true' ? {} : { maxWorkers: defaultParallelism(process.env, undefined, LOCAL_TEST_PARALLELISM_CAP) }
|
|
|
|
// These suites exercise process-global state, process APIs, or timing-sensitive process I/O
|
|
// that worker threads cannot isolate reliably under aggregate gate contention.
|
|
// Keep the narrow exception in forks while the rest of the inventory avoids per-file processes.
|
|
const processBoundTests = [
|
|
'packages/session/session-persistence-jsonl/tests/jsonl.spec.ts',
|
|
'packages/subagent/subagent-acp/tests/subagent-acp.spec.ts',
|
|
'packages/subprocess/subprocess-local/tests/process-exit.spec.ts',
|
|
'packages/subprocess/subprocess-local/tests/spawn.spec.ts',
|
|
'packages/context/time-context/tests/time-context.spec.ts',
|
|
'packages/llm/llm-pi-ai/tests/adapter.spec.ts',
|
|
'packages/boot/app-boot/tests/app-boot.spec.ts',
|
|
'packages/workflow/workflow-ptc/tests/workflow-ptc.spec.ts',
|
|
]
|
|
|
|
// Claude Code's test-kit module names, served by the mods bridge's test support so the example mods' tests import them unchanged.
|
|
const claudeCodeTestingAliases = {
|
|
'claude-code/testing': fileURLToPath(new URL('./packages/experimental/claude-code-mods/tests/support/claude-code-testing.ts', import.meta.url)),
|
|
'claude-code': fileURLToPath(new URL('./packages/experimental/claude-code-mods/tests/support/claude-code.ts', import.meta.url)),
|
|
}
|
|
|
|
export default defineConfig({
|
|
plugins: [pathsPlugin(), standardDecoratorPlugin()],
|
|
resolve: { alias: claudeCodeTestingAliases },
|
|
test: {
|
|
...localWorkerBudget,
|
|
setupFiles: [
|
|
'./scripts/test-proxy-environment.ts', './scripts/test-dom-environment.ts', './scripts/test-official-listing-guard.ts',
|
|
],
|
|
// .tsx: client component specs (jsdom via per-file @vitest-environment pragma).
|
|
include: testIncludes,
|
|
exclude: platformUnsupportedTests,
|
|
// One coverage invocation aggregates both projects. Every suite forks for
|
|
// Node stability; process-bound suites stay separate for inventory control.
|
|
projects: [
|
|
{
|
|
plugins: [pathsPlugin(), standardDecoratorPlugin()],
|
|
resolve: { alias: claudeCodeTestingAliases },
|
|
test: {
|
|
name: 'thread-safe',
|
|
execArgv: vitestExecArgv,
|
|
// Node 24 has aborted in its CJS lexer (v8::ToLocalChecked Empty
|
|
// MaybeLocal in cjs_lexer::Parse) from worker threads on macOS,
|
|
// Linux, and Windows. Forked workers avoid that shared thread path.
|
|
pool: 'forks',
|
|
...laneTestBudget,
|
|
setupFiles: [
|
|
'./scripts/test-proxy-environment.ts', './scripts/test-dom-environment.ts', './scripts/test-official-listing-guard.ts',
|
|
],
|
|
include: testIncludes,
|
|
exclude: [
|
|
...platformUnsupportedTests,
|
|
...processBoundTests,
|
|
...coverageExemptExcludes,
|
|
],
|
|
},
|
|
},
|
|
{
|
|
plugins: [pathsPlugin(), standardDecoratorPlugin()],
|
|
resolve: { alias: claudeCodeTestingAliases },
|
|
test: {
|
|
name: 'process-bound',
|
|
execArgv: vitestExecArgv,
|
|
pool: 'forks',
|
|
...laneTestBudget,
|
|
setupFiles: [
|
|
'./scripts/test-proxy-environment.ts', './scripts/test-dom-environment.ts', './scripts/test-official-listing-guard.ts',
|
|
],
|
|
include: processBoundTests,
|
|
exclude: [
|
|
...platformUnsupportedTests,
|
|
...coverageExemptExcludes,
|
|
],
|
|
},
|
|
},
|
|
],
|
|
coverage: {
|
|
provider: 'v8',
|
|
// Coverage measures OUR runtime source. Types-only files carry no
|
|
// executable code; vendor/ and application/config fixtures are out of scope.
|
|
// .tsx: client components are gated like everything else (jsdom lane).
|
|
include: ['packages/*/*/src/**/*.{ts,tsx}'],
|
|
// Types-only files have no runtime coverage. Importing self-executing bins/workers would boot
|
|
// them inside the unit process, so real subprocess/Worker tests cover their thin entry glue.
|
|
exclude: [
|
|
'packages/*/*/src/types.ts',
|
|
'packages/*/*/src/bin.ts',
|
|
'packages/*/*/src/worker.ts',
|
|
// The built Node entry invokes the independently covered process bootstrap through fd 7.
|
|
'packages/ptc-runtime/ptc-runtime-node/src/process-entry.ts',
|
|
'packages/ptc-runtime/ptc-runtime-node/src/persistent-process-entry.ts',
|
|
// Dynamic Host/Client composition is covered by its focused lifecycle
|
|
// tests and assembled application checks rather than per-file coverage.
|
|
'packages/self-modification/*/src/**/*.{ts,tsx}',
|
|
// A killed executable lint-contract test can leave a non-product source probe behind.
|
|
'packages/*/*/src/oxlint-contract-*.ts',
|
|
// Client/web UI files whose remaining branches need a browser-grade
|
|
// harness the jsdom lane doesn't cover yet. TODO(gui): cover and
|
|
// remove as the client test lane matures.
|
|
'packages/client/ui-trajectory/src/*',
|
|
// Electron guest integration retains its unit specs; per-file coverage
|
|
// is deferred until a native Electron harness covers guest behavior.
|
|
'packages/client/ui-sidebar-browser/src/client/electron/**',
|
|
// Trajectory's compact Markdown projection retains deferred branch coverage.
|
|
'packages/client/ui-primitives/src/markdown/plain-text.ts',
|
|
'packages/client/ui-user-questions/src/client/QuestionComposer.tsx',
|
|
'packages/client/ui-primitives/src/Menu.tsx',
|
|
'packages/client/ui-primitives/src/RiskConfirmation.tsx',
|
|
'packages/client/ui-workspace/src/client/WorkspaceBrowser.tsx',
|
|
'packages/client/ui-workspace/src/client/WorkspacePicker.tsx',
|
|
'packages/client/ui-workspace/src/client/rows/WorkspaceBrowser.tsx',
|
|
'packages/client/ui-renderer/src/client/*',
|
|
// Session object internals retain the runtime GUI debt exemption; the
|
|
// assistant-stream reconciler, Controller entry, transport, Agent scope,
|
|
// and adapters stay gated.
|
|
'packages/api/session-controller/src/client/sessions/!(assistant-stream).ts',
|
|
'packages/api/session-controller/src/client/ordered-baseline.ts',
|
|
'packages/api/session-controller/src/client/time-zone.ts',
|
|
// Keep the browser conversation tree under its existing GUI debt
|
|
// exemption while gating the newly stateful Host half and vocabulary.
|
|
'packages/client/ui-conversation/src/client/*',
|
|
// Chat presentation and assembly retain the same GUI debt exemption;
|
|
// package wiring and the new approval-detail adapter remain gated.
|
|
'packages/client/ui-chat/src/client/chat/!(ApprovalCommand).{ts,tsx}',
|
|
'packages/client/ui-chat/src/client/conversation-nodes/*',
|
|
'packages/client/ui-chat/src/client/details/*',
|
|
'packages/client/ui-chat/src/client/model/*',
|
|
'packages/client/ui-chat/src/client/contract/snapshot.ts',
|
|
'packages/client/ui-chat/src/client/historical-images.ts',
|
|
'packages/client/ui-primitives/src/DisclosureRow.tsx',
|
|
'packages/client/ui-tool/src/*',
|
|
'packages/client/ui-slots/src/*',
|
|
'packages/client/ui-layout/src/*',
|
|
'packages/client/web/src/*',
|
|
'packages/host/webserver/src/*',
|
|
// The browser-worker runtime and its image packer: the executing
|
|
// composition is a real dedicated Worker driven by the web browser lane
|
|
// (apps/web/tests/preview-boot.e2e.ts), which unit-process V8 coverage
|
|
// cannot observe. Unit specs cover the algorithmic cores; the assembled
|
|
// evidence is that boot. TODO(webworker): revisit when a browser-grade
|
|
// coverage lane exists.
|
|
'packages/experimental/webworker-runtime/src/**',
|
|
'packages/experimental/webworker-packer/src/*',
|
|
// Inspector execution adapters run in a Node Worker, the Host native
|
|
// inspector session, or a browser realm, outside attributable parent
|
|
// Vitest coverage.
|
|
'packages/experimental/inspector/src/client/**',
|
|
'packages/experimental/inspector/src/host/bridge/**',
|
|
'packages/experimental/inspector/src/host/cdp/**',
|
|
'packages/experimental/inspector/src/worker/bridge/**',
|
|
'packages/experimental/inspector/src/worker/cdp/**',
|
|
'packages/experimental/inspector/src/worker/realms/**',
|
|
'packages/experimental/inspector/src/worker/{entry,server}.ts',
|
|
// Keep already-complete Inspector modules under the per-file gate and
|
|
// enumerate the remaining direct-test debt instead of exempting src/**.
|
|
// TODO(inspector): close these branch gaps and remove the entries.
|
|
'packages/experimental/inspector/src/shared/bridge/{control-codec,rpc}.ts',
|
|
'packages/experimental/inspector/src/shared/bridge/messages/observation.ts',
|
|
'packages/experimental/inspector/src/shared/bridge/messages/query/codec.ts',
|
|
'packages/experimental/inspector/src/shared/bridge/messages/runtime/{command-codec,console-frames,frames,value-codec}.ts',
|
|
'packages/experimental/inspector/src/shared/bridge/messages/sources/{codec,frames}.ts',
|
|
'packages/experimental/inspector/src/worker/inspection/{cordis-store,query-router,realm-store}.ts',
|
|
// Web config-tree boot round: the new host-side web-transport halves
|
|
// whose remaining branches need real-composition/process harnesses.
|
|
// TODO(gui): cover and remove with the client test lane above.
|
|
'packages/client/modules/src/index.ts',
|
|
'packages/client/modules/src/client/index.ts',
|
|
'packages/client/modules/src/client/manifest.ts',
|
|
'packages/client/hmr/src/index.ts',
|
|
'packages/client/connection/src/index.ts',
|
|
'packages/client/connection/src/http-bridge.ts',
|
|
// This assembly imports generated Host-for-Client code that exists
|
|
// only in lib; the post-build built-bin smoke executes both entries.
|
|
'packages/api/remotes/src/index.ts',
|
|
'packages/api/remotes/src/client/index.ts',
|
|
// The Team browser entry binds its source-covered mount lifecycle to
|
|
// the generated Team Remote contribution, which likewise exists only in lib.
|
|
'packages/experimental/client-ui-agent-team/src/client/index.ts',
|
|
// The speech entry also imports generated Remote definitions; voice-input.e2e.ts
|
|
// exercises the built entry, while source tests cover mountVoiceInput.
|
|
'packages/experimental/client-ui-voice-input/src/client/index.ts',
|
|
// The mods band entry imports the bridge's generated Remote contribution, which exists only in lib;
|
|
// the Web snapshot exercises the built entry, while source tests cover mountModsBand.
|
|
'packages/experimental/client-ui-claude-code-mods/src/client/index.ts',
|
|
// The access entry imports its generated Remote contribution, which exists only in lib;
|
|
// the Web snapshot exercises the built entry, while source tests cover mountAccess.
|
|
'packages/api/remote-access/src/client/index.ts',
|
|
// Slash/command/input round: per-file gaps deferred with the same
|
|
// client-lane debt. TODO(gui): cover and remove with the lane above.
|
|
'packages/client/ui-commands/src/index.ts',
|
|
'packages/client/ui-skill/src/index.ts',
|
|
'packages/client/ui-input-trigger/src/index.ts',
|
|
'packages/client/ui-subagent/src/index.ts',
|
|
'packages/client/ui-commands/src/client/popup.ts',
|
|
'packages/client/ui-commands/src/client/directory.ts',
|
|
'packages/client/ui-commands/src/client/service.ts',
|
|
'packages/client/ui-commands/src/client/PopupSelectView.tsx',
|
|
'packages/client/ui-model-selection/src/index.ts',
|
|
'packages/client/ui-permission-presets/src/index.ts',
|
|
'packages/client/ui-model-selection/src/client/ModelSelect.tsx',
|
|
'packages/client/ui-model-selection/src/client/directory.ts',
|
|
'packages/client/ui-model-selection/src/client/index.ts',
|
|
'packages/client/ui-model-selection/src/client/service.ts',
|
|
'packages/client/ui-input-trigger/src/client/controller.ts',
|
|
'packages/client/ui-input-trigger/src/client/service.ts',
|
|
'packages/client/ui-input-trigger/src/core/menu.ts',
|
|
'packages/client/ui-input-trigger/src/core/detect.ts',
|
|
'packages/client/ui-sidebar/src/client/index.ts',
|
|
'packages/client/ui-skill/src/client/index.ts',
|
|
'packages/client/ui-workspace/src/client/index.ts',
|
|
'packages/test-support/client-runtime/src/translate.ts',
|
|
'packages/client/ui-primitives/src/JsonTree.tsx',
|
|
'packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.tsx',
|
|
'packages/client/ui-settings-models/src/client/welcome-store.ts',
|
|
'packages/extensions/*/src/**/*.ts',
|
|
'packages/extensions/*/src/**/*.tsx',
|
|
// Typert correctness is checked by its uninstrumented suites,
|
|
// including compiler fixtures and byte-for-byte catalog reproduction.
|
|
'packages/typert/*/src/**/*.{ts,tsx}',
|
|
// Experimental webworker-runtime is outside the coverage requirement
|
|
// by decision: its correctness signal is its uninstrumented suite and
|
|
// the packer's end-to-end image spec.
|
|
'packages/experimental/webworker-runtime/src/**/*.ts',
|
|
// Projection/command round: executor lifecycle branches and the
|
|
// registry's drive tails need the same maturing lanes. TODO(gui):
|
|
// cover and remove with the client test lane above.
|
|
'packages/interaction/commands/src/index.ts',
|
|
'packages/session/session-projection/src/index.ts',
|
|
...windowsUnsupportedCoveragePackages.map(path => `${path}/src/**/*.ts`),
|
|
...windowsOnlyCoverageExclusions,
|
|
...windowsRunnerCoverageExclusions,
|
|
...pwshCoverageExclusions,
|
|
],
|
|
// 100% or it doesn't merge (docs/testing.md: excessive tests are welcome).
|
|
// Per-file so a well-covered big file can't subsidize a bare one.
|
|
// Every v8 ignore comment must carry a reason — see the testing policy
|
|
// (docs/testing.md).
|
|
thresholds: coveragePartitionMode
|
|
? undefined
|
|
: {
|
|
perFile: true,
|
|
statements: 100,
|
|
branches: 100,
|
|
functions: 100,
|
|
lines: 100,
|
|
},
|
|
reporter: coveragePartitionMode
|
|
? []
|
|
: process.env.CI
|
|
? ['text', uncoveredLocationsReporter]
|
|
: ['text', 'html', uncoveredLocationsReporter],
|
|
},
|
|
},
|
|
})
|