fix(rebase): migrate the replayed stack onto current master APIs
The linear replay carried each commit's own lineage, so this checkpoint restores the master-owned surfaces the conflicted regions clobbered and migrates branch-owned code to master's post-rebase APIs: - rebuild subprocess-local spawn.ts on master's tree-exit-observer machinery, keeping the branch's win32 childEnv key semantics and the Linux zombie-quiescence probe; the zombie test reaps its survivor directly since a confirmed-absent verdict is a permanent no-more-signals boundary - migrate pty-local test stubs to the Inbox-model Agent interface, Session.create, runnerFailureRules, and the new turn/start payload - implement the seam's resolveExecutable/spawnTerminal abstracts in the new pwsh-local and tool-fs-search test fakes - restore code-runtime, atomic-write, pwsh-local, and app-boot to master's exact content (the net-zero code-runtime churn is pruned from this history) and drop rename-detection graft debris - re-apply the PR's architecture rows and execution-world paragraph, re-record bilingual pairings, regenerate catalogs, and reconcile the lockfile
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||
import { resolvePwshPath } from './packages/bash/pwsh-local/src/resolve.ts'
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import { vitestExecArgv } from './vitest.shared.ts'
|
||||
import { COVERAGE_EXEMPT_ENV, coverageExemptHeavySuites } from './scripts/coverage-exempt.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
|
||||
@@ -9,7 +20,14 @@ const pathsPlugin = (): ReturnType<typeof tsconfigPaths> => tsconfigPaths({ proj
|
||||
|
||||
const windowsUnsupportedPackages = process.platform === 'win32'
|
||||
? [
|
||||
'packages/bash/*',
|
||||
// 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.
|
||||
// Replacing the old 'packages/bash/*' glob with this explicit list also
|
||||
// newly INCLUDES packages/bash/bash (the pure seam package) on Windows.
|
||||
'packages/bash/bash-local',
|
||||
'packages/bash/bash-sandbox',
|
||||
'packages/bash/tool-bash',
|
||||
'packages/hooks/*',
|
||||
'packages/subprocess/*',
|
||||
'packages/pty/pty-local',
|
||||
@@ -26,10 +44,20 @@ const windowsCoverageExclusions = process.platform === 'win32'
|
||||
'packages/lsp/lsp-local/src/connection.ts',
|
||||
'packages/lsp/lsp-local/src/index.ts',
|
||||
'packages/lsp/lsp-local/src/instance.ts',
|
||||
'packages/ui/tui/src/index.ts',
|
||||
]
|
||||
: []
|
||||
|
||||
// Mirrors windowsCoverageExclusions: 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/bash/pwsh-local/src/index.ts']
|
||||
|
||||
const testIncludes = [
|
||||
'packages/*/*/tests/**/*.spec.{ts,tsx}',
|
||||
'apps/*/tests/**/*.spec.ts',
|
||||
@@ -37,6 +65,17 @@ const testIncludes = [
|
||||
'scripts/**/*.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)
|
||||
: []
|
||||
|
||||
// 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.
|
||||
@@ -55,22 +94,27 @@ export default defineConfig({
|
||||
// .tsx: client component specs (jsdom via per-file @vitest-environment pragma).
|
||||
include: testIncludes,
|
||||
exclude: windowsUnsupportedPackages.map(path => `${path}/tests/**/*.spec.ts`),
|
||||
// One coverage invocation aggregates both projects. Most suites use threads
|
||||
// for lower startup/IPC overhead; only explicit process-bound suites fork.
|
||||
// One coverage invocation aggregates both projects. Regular suites fork on
|
||||
// POSIX for Node stability and use threads on Windows; process-bound suites
|
||||
// always fork.
|
||||
projects: [
|
||||
{
|
||||
plugins: [pathsPlugin()],
|
||||
test: {
|
||||
name: 'thread-safe',
|
||||
// Node 24 has aborted in its CJS lexer from a macOS arm64 worker
|
||||
// thread. A fork contains that external runtime failure to the test
|
||||
// process; other hosts retain the lower-overhead thread pool.
|
||||
pool: process.platform === 'darwin' ? 'forks' : 'threads',
|
||||
execArgv: vitestExecArgv,
|
||||
// Node 24 has aborted in its CJS lexer (v8::ToLocalChecked Empty
|
||||
// MaybeLocal in cjs_lexer::Parse) from worker threads on macOS
|
||||
// arm64 and later on Linux. A fork contains that external runtime
|
||||
// failure to the test process; Windows keeps the thread pool, where
|
||||
// the abort has not reproduced and process spawn is costlier.
|
||||
pool: process.platform === 'win32' ? 'threads' : 'forks',
|
||||
setupFiles: ['./scripts/test-invariants.ts'],
|
||||
include: testIncludes,
|
||||
exclude: [
|
||||
...windowsUnsupportedPackages.map(path => `${path}/tests/**/*.spec.ts`),
|
||||
...processBoundTests,
|
||||
...coverageExemptExcludes,
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -78,10 +122,14 @@ export default defineConfig({
|
||||
plugins: [pathsPlugin()],
|
||||
test: {
|
||||
name: 'process-bound',
|
||||
execArgv: vitestExecArgv,
|
||||
pool: 'forks',
|
||||
setupFiles: ['./scripts/test-invariants.ts'],
|
||||
include: processBoundTests,
|
||||
exclude: windowsUnsupportedPackages.map(path => `${path}/tests/**/*.spec.ts`),
|
||||
exclude: [
|
||||
...windowsUnsupportedPackages.map(path => `${path}/tests/**/*.spec.ts`),
|
||||
...coverageExemptExcludes,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -98,7 +146,8 @@ export default defineConfig({
|
||||
'packages/*/*/src/types.ts',
|
||||
'packages/*/*/src/bin.ts',
|
||||
'packages/*/*/src/worker.ts',
|
||||
'packages/code-runtime/code-runtime-subprocess/src/runner.ts',
|
||||
// A killed executable lint-contract test can leave a non-product source probe behind.
|
||||
'packages/*/*/src/oxlint-contract-*.ts',
|
||||
// GUI step-1 skeleton (PR #500): 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.
|
||||
@@ -107,6 +156,7 @@ export default defineConfig({
|
||||
'packages/client/ui-primitives/src/markdown/plain-text.ts',
|
||||
'packages/client/ui-question/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/web-react/src/*',
|
||||
@@ -155,9 +205,13 @@ export default defineConfig({
|
||||
'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/typert/generator/src/analyzer.ts',
|
||||
'packages/typert/generator/src/renderer.ts',
|
||||
'packages/typert/generator/src/cordis-catalog.ts',
|
||||
'packages/client/test-runtime/src/translate.ts',
|
||||
'packages/client/ui-primitives/src/JsonTree.tsx',
|
||||
// Typert generator: correctness is pinned by its fixture suites and
|
||||
// the byte-for-byte catalog reproduction test; per-file coverage
|
||||
// would put whole-workspace compiler analysis under v8
|
||||
// instrumentation — the coverage lane's longest tail.
|
||||
'packages/typert/generator/src/*.ts',
|
||||
'packages/host/apiproxy/src/index.ts',
|
||||
'packages/host/apiproxy/src/invariant.ts',
|
||||
'packages/host/apiproxy/src/api-proxy.ts',
|
||||
@@ -167,9 +221,9 @@ export default defineConfig({
|
||||
'packages/ui/commands/src/index.ts',
|
||||
'packages/ui/commands/src/invariant.ts',
|
||||
'packages/session-projection/session-projection/src/index.ts',
|
||||
'packages/ui/tui/src/index.ts',
|
||||
...windowsUnsupportedPackages.map(path => `${path}/src/**/*.ts`),
|
||||
...windowsCoverageExclusions,
|
||||
...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.
|
||||
@@ -182,7 +236,9 @@ export default defineConfig({
|
||||
functions: 100,
|
||||
lines: 100,
|
||||
},
|
||||
reporter: process.env.CI ? ['text'] : ['text', 'html'],
|
||||
reporter: process.env.CI
|
||||
? ['text', uncoveredLocationsReporter]
|
||||
: ['text', 'html', uncoveredLocationsReporter],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user