dsh-context-compression-improved 0.2.1 → 0.3.1
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/.gitattributes +1 -1
- package/.github/workflows/ci.yml +1 -7
- package/CHANGELOG.ja.md +18 -21
- package/CHANGELOG.ko.md +17 -21
- package/CHANGELOG.md +16 -17
- package/CHANGELOG.zh.md +15 -18
- package/CONTRIBUTING.md +1 -1
- package/README.ja.md +1 -20
- package/README.ko.md +12 -30
- package/README.md +1 -19
- package/README.zh.md +5 -21
- package/THIRD_PARTY_NOTICES.md +2 -2
- package/docs/compat-0.1.5-report.md +77 -0
- package/docs/installation.ja.md +6 -4
- package/docs/installation.ko.md +9 -7
- package/docs/installation.md +3 -1
- package/docs/installation.zh.md +3 -2
- package/docs/repair-log.md +54 -33
- package/eslint.config.js +2 -2
- package/package.json +56 -36
- package/packages/selector/README.md +7 -12
- package/packages/selector/README.zh.md +6 -13
- package/packages/selector/THIRD_PARTY_NOTICES.md +2 -8
- package/packages/selector/cordis.patch.yml +7 -5
- package/packages/selector/dsh.plugin.json +2 -2
- package/packages/selector/lib/client.d.ts +31 -5
- package/packages/selector/lib/client.js +100 -82
- package/packages/selector/lib/index.d.ts +8 -20
- package/packages/selector/lib/index.js +9 -14
- package/packages/selector/lib/invariant.js +4 -4
- package/packages/selector/lib/pruner.d.ts +13 -4
- package/packages/selector/lib/pruner.js +91 -46
- package/packages/selector/lib/tail-trim.js +13 -4
- package/packages/selector/package.json +23 -23
- package/packages/selector/screenshots.json +1 -4
- package/packages/selector/src/client/CompressionProfileControls.tsx +5 -8
- package/packages/selector/src/client/CompressionProfileSelector.tsx +9 -5
- package/packages/selector/src/client/EstimatorControls.tsx +28 -32
- package/packages/selector/src/client/index.ts +101 -63
- package/packages/selector/src/client/locales.ts +0 -2
- package/packages/selector/src/client/preset-options.ts +49 -35
- package/packages/selector/src/client/settings-section.tsx +4 -6
- package/packages/selector/src/deepseek-v4-tokenizer.ts +0 -5
- package/packages/selector/src/index.ts +41 -46
- package/packages/selector/src/invariant.ts +5 -5
- package/packages/selector/src/pruner.ts +67 -36
- package/packages/selector/src/runtime/measurement.ts +6 -2
- package/packages/selector/src/runtime/session-events.ts +14 -1
- package/packages/selector/src/runtime/tail-trim.ts +4 -4
- package/packages/selector/src/runtime/tokenpilot/estimator.ts +34 -3
- package/packages/selector/src/runtime/types.ts +1 -1
- package/packages/selector/tests/auto-compact.client.spec.tsx +0 -13
- package/packages/selector/tests/built/client-artifact.spec.ts +5 -1
- package/packages/selector/tests/code-skeleton.client.spec.ts +2 -1
- package/packages/selector/tests/custom-contract.client.spec.ts +2 -1
- package/packages/selector/tests/estimator-channel.client.spec.tsx +16 -11
- package/packages/selector/tests/estimator-route-registration.host.spec.ts +12 -0
- package/packages/selector/tests/host-preset-overlay.host.spec.ts +6 -4
- package/packages/selector/tests/preset-options-write.client.spec.ts +87 -79
- package/packages/selector/tests/preset-overlay-loader.e2e.host.spec.ts +17 -12
- package/packages/selector/tests/preset-overlay.host.spec.ts +5 -2
- package/packages/selector/tests/profiles.client.spec.tsx +3 -3
- package/packages/selector/tests/public/package-contract.client.spec.ts +27 -3
- package/packages/selector/tests/runtime/public/public-runtime.spec.ts +103 -81
- package/packages/selector/tests/runtime/session-events.spec.ts +1 -1
- package/packages/selector/tests/settings-seat.client.spec.ts +86 -0
- package/packages/selector/tests/standing-generation.host.spec.ts +88 -71
- package/packages/selector/tests/subagent-cache-reuse.host.spec.ts +24 -21
- package/pnpm-workspace.yaml +52 -5
- package/scripts/capture-profile-baseline.mjs +42 -0
- package/scripts/generate-tokenizer-fixtures.py +5 -5
- package/scripts/generate-vision-fixtures.py +2 -2
- package/scripts/{packed-components-smoke.ts → packed-components-smoke.mjs} +116 -119
- package/scripts/{packed-install-e2e.ts → packed-install-e2e.mjs} +188 -160
- package/scripts/{verify-release.ts → verify-release.mjs} +70 -94
- package/tests/TEST_INVENTORY.md +6 -7
- package/scripts/capture-profile-baseline.ts +0 -80
- package/tsconfig.scripts.json +0 -13
- /package/{packages/selector/assets/screenshots → docs/assets}/context-compression-selector-profiles.jpg +0 -0
- /package/{packages/selector/assets/screenshots → docs/assets}/context-compression-selector-settings.png +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process'
|
|
2
1
|
import { createHash } from 'node:crypto'
|
|
3
2
|
import { readdir, readFile, stat } from 'node:fs/promises'
|
|
4
3
|
import { join, relative } from 'node:path'
|
|
@@ -6,42 +5,62 @@ import { fileURLToPath } from 'node:url'
|
|
|
6
5
|
|
|
7
6
|
const root = fileURLToPath(new URL('..', import.meta.url))
|
|
8
7
|
|
|
9
|
-
const fail = (message
|
|
8
|
+
const fail = (message) => {
|
|
10
9
|
throw new Error(`release verification: ${message}`)
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
const json = async (path
|
|
12
|
+
const json = async (path) => JSON.parse(await readFile(path, 'utf8'))
|
|
14
13
|
const rootPackage = await json(join(root, 'package.json'))
|
|
15
|
-
const selectorPackage = await json(join(root, 'packages/selector/package.json'))
|
|
14
|
+
const selectorPackage = await json(join(root, 'packages/selector/package.json'))
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (!(rootScripts?.typecheck as string)?.includes('pnpm run typecheck:tests')
|
|
21
|
-
|| rootScripts?.['typecheck:tests'] !== 'tsc --noEmit -p tsconfig.tests.json') {
|
|
16
|
+
if (!rootPackage.scripts?.typecheck?.includes('pnpm run typecheck:tests')
|
|
17
|
+
|| rootPackage.scripts?.['typecheck:tests'] !== 'tsc --noEmit -p tsconfig.tests.json') {
|
|
22
18
|
fail('root typecheck must include the strict active-test TypeScript gate')
|
|
23
19
|
}
|
|
24
|
-
|
|
20
|
+
// The root manifest is the install surface for git installs: one package
|
|
21
|
+
// carries the runtime, the settings UI and the bundle patch.
|
|
22
|
+
if (rootPackage.name !== 'dsh-context-compression-improved') fail('unexpected root package name')
|
|
23
|
+
for (const specifier of ['.', './invariant', './pruner', './client']) {
|
|
24
|
+
if (rootPackage.exports?.[specifier] === undefined) {
|
|
25
|
+
fail(`root exports are missing the ${specifier} specifier`)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (rootPackage.dsh?.bundle?.patch !== './packages/selector/cordis.patch.yml') {
|
|
29
|
+
fail('root must declare the DSH Bundle patch of the selector package')
|
|
30
|
+
}
|
|
31
|
+
for (const dependency of ['@huggingface/tokenizers', 'js-yaml']) {
|
|
32
|
+
if (rootPackage.dependencies?.[dependency] === undefined) {
|
|
33
|
+
fail(`root dependencies are missing ${dependency}`)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const specifier of ['.', './invariant', './pruner', './client']) {
|
|
37
|
+
if (selectorPackage.exports?.[specifier] === undefined) {
|
|
38
|
+
fail(`selector exports are missing the ${specifier} specifier`)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (selectorPackage.scripts?.test
|
|
25
42
|
!== 'vitest run --root ../.. --config vitest.config.ts --project runtime --project selector-host --project selector-client') {
|
|
26
|
-
fail('
|
|
43
|
+
fail('Selector package-local test script is not the verified root project command')
|
|
27
44
|
}
|
|
28
45
|
const ci = await readFile(join(root, '.github/workflows/ci.yml'), 'utf8')
|
|
29
|
-
|
|
30
|
-
|
|
46
|
+
for (const required of [
|
|
47
|
+
'pnpm --filter dsh-context-compression-improved test',
|
|
48
|
+
]) {
|
|
49
|
+
if (!ci.includes(required)) fail(`CI lacks package-local gate: ${required}`)
|
|
31
50
|
}
|
|
32
51
|
// The packed release E2E is the release gate that actually installs the
|
|
33
52
|
// tarballs: verify it cannot be silently dropped or defanged. It must exist
|
|
34
53
|
// as a root script, CI must run exactly that script, the script must default
|
|
35
54
|
// to fail-closed release mode, and that mode must refuse every skip/null
|
|
36
55
|
// lifecycle outcome.
|
|
37
|
-
if (
|
|
56
|
+
if (rootPackage.scripts?.['test:e2e:packed'] !== 'node scripts/packed-install-e2e.mjs') {
|
|
38
57
|
fail('root test:e2e:packed script is missing or does not run the packed E2E directly')
|
|
39
58
|
}
|
|
40
59
|
if (!ci.includes('pnpm run test:e2e:packed') && !ci.includes('pnpm test:e2e:packed')) {
|
|
41
60
|
fail('CI does not run the packed release E2E gate')
|
|
42
61
|
}
|
|
43
|
-
const packedE2e = await readFile(join(root, 'scripts/packed-install-e2e.
|
|
44
|
-
if (!/const e2eMode
|
|
62
|
+
const packedE2e = await readFile(join(root, 'scripts/packed-install-e2e.mjs'), 'utf8')
|
|
63
|
+
if (!/const e2eMode = process\.env\.DSH_E2E_MODE === 'dev' \? 'dev' : 'release'/u.test(packedE2e)) {
|
|
45
64
|
fail('packed E2E must default to release mode (dev only via an explicit DSH_E2E_MODE)')
|
|
46
65
|
}
|
|
47
66
|
for (const failClosed of [
|
|
@@ -52,7 +71,7 @@ for (const failClosed of [
|
|
|
52
71
|
fail(`packed E2E release mode lost its fail-closed guard: ${failClosed}`)
|
|
53
72
|
}
|
|
54
73
|
}
|
|
55
|
-
const packedComponents = await readFile(join(root, 'scripts/packed-components-smoke.
|
|
74
|
+
const packedComponents = await readFile(join(root, 'scripts/packed-components-smoke.mjs'), 'utf8')
|
|
56
75
|
for (const required of [
|
|
57
76
|
'Runtime.measureForCompaction(visionCtx, visionImage)',
|
|
58
77
|
"estimatedImageCount?.kind === 'tokenizer-estimate'",
|
|
@@ -77,36 +96,30 @@ for (const required of [
|
|
|
77
96
|
}
|
|
78
97
|
await stat(join(root, 'tsconfig.tests.json'))
|
|
79
98
|
|
|
80
|
-
if (
|
|
99
|
+
if (selectorPackage.dsh?.bundle?.patch !== './cordis.patch.yml') {
|
|
81
100
|
fail('selector must declare the DSH Bundle patch')
|
|
82
101
|
}
|
|
83
|
-
if (
|
|
102
|
+
if (selectorPackage.files?.some((entry) => entry.endsWith('.css'))) {
|
|
84
103
|
fail('selector must not rely on separately served CSS assets')
|
|
85
104
|
}
|
|
86
|
-
if (
|
|
87
|
-
if (
|
|
88
|
-
if (
|
|
105
|
+
if (selectorPackage.name !== 'dsh-context-compression-improved') fail('unexpected selector package name')
|
|
106
|
+
if (selectorPackage.publishConfig?.access !== 'public') fail('selector publish access is not public')
|
|
107
|
+
if (selectorPackage.publishConfig?.tag !== 'latest') fail('selector publish tag is not latest')
|
|
89
108
|
for (const peer of [
|
|
90
109
|
'@deepseek-ai/dsh-command-compact',
|
|
91
110
|
'@deepseek-ai/dsh-compaction-basic',
|
|
92
111
|
]) {
|
|
93
|
-
if (
|
|
112
|
+
if (selectorPackage.peerDependencies?.[peer] !== '>=0.1.5-rc.2 <0.2.0-0') {
|
|
94
113
|
fail(`selector peer ${peer} is missing or outside the verified range`)
|
|
95
114
|
}
|
|
96
115
|
}
|
|
97
|
-
const
|
|
116
|
+
const packageRoot = join(root, 'packages/selector')
|
|
117
|
+
const notice = await readFile(join(packageRoot, 'THIRD_PARTY_NOTICES.md'), 'utf8')
|
|
98
118
|
if (!notice.includes('Copyright (c) 2026 DeepSeek')) {
|
|
99
119
|
fail('packages/selector does not carry the full DeepSeek Harness MIT notice')
|
|
100
120
|
}
|
|
101
121
|
|
|
102
|
-
|
|
103
|
-
directory: string
|
|
104
|
-
repository: string
|
|
105
|
-
modelIds: string
|
|
106
|
-
revision?: string
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const assetManifests: AssetManifest[] = [
|
|
122
|
+
const assetManifests = [
|
|
110
123
|
{
|
|
111
124
|
directory: 'deepseek-v4',
|
|
112
125
|
repository: 'deepseek-ai/DeepSeek-V4-Pro',
|
|
@@ -121,12 +134,7 @@ const assetManifests: AssetManifest[] = [
|
|
|
121
134
|
]
|
|
122
135
|
for (const expected of assetManifests) {
|
|
123
136
|
const assetRoot = join(root, 'packages/selector/assets', expected.directory)
|
|
124
|
-
const manifest = await json(join(assetRoot, 'manifest.json'))
|
|
125
|
-
repository: string
|
|
126
|
-
modelIds: string[]
|
|
127
|
-
revision?: string
|
|
128
|
-
files: Record<string, { bytes: number; sha256: string }>
|
|
129
|
-
}
|
|
137
|
+
const manifest = await json(join(assetRoot, 'manifest.json'))
|
|
130
138
|
if (manifest.repository !== expected.repository) fail(`${expected.directory} manifest repository differs`)
|
|
131
139
|
if (!JSON.stringify(manifest.modelIds).includes(expected.modelIds)) {
|
|
132
140
|
fail(`${expected.directory} manifest model ids differ`)
|
|
@@ -139,11 +147,15 @@ for (const expected of assetManifests) {
|
|
|
139
147
|
const hash = createHash('sha256').update(bytes).digest('hex')
|
|
140
148
|
if (bytes.byteLength !== descriptor.bytes) fail(`${expected.directory}/${name} byte length differs from manifest`)
|
|
141
149
|
if (hash !== descriptor.sha256) fail(`${expected.directory}/${name} SHA-256 differs from manifest`)
|
|
150
|
+
// A checkout with core.autocrlf=true can rewrite these pinned bytes as CRLF;
|
|
151
|
+
// the `-text` attribute in .gitattributes prevents it, but only while the
|
|
152
|
+
// pattern still matches the path. Catch it here rather than in a consumer
|
|
153
|
+
// whose tokenizer would fail its own integrity check at run time.
|
|
154
|
+
if (bytes.includes(0x0d)) fail(`${expected.directory}/${name} contains CR bytes; the asset was rewritten`)
|
|
142
155
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
fail(`package files list omits assets for ${expected.directory}`)
|
|
156
|
+
const assetEntries = selectorPackage.files ?? []
|
|
157
|
+
if (!assetEntries.some(entry => entry === 'assets' || entry.startsWith('assets/'))) {
|
|
158
|
+
fail('selector package files list omits the tokenizer assets')
|
|
147
159
|
}
|
|
148
160
|
}
|
|
149
161
|
|
|
@@ -153,11 +165,13 @@ const forbidden = [
|
|
|
153
165
|
{ pattern: /@deepseek-ai\/[^'"\s]+\/src(?:\/|['"])/u, label: 'Harness source subpath import' },
|
|
154
166
|
{ pattern: /(?:\/home\/|[A-Za-z]:\\Users\\)/u, label: 'developer absolute path' },
|
|
155
167
|
{ pattern: /\.\.\/\.\.\/\.\.\/(?:core|packages)\//u, label: 'monorepo-relative source import' },
|
|
168
|
+
// The single-package merge must not leave a cross-package import behind.
|
|
169
|
+
{ pattern: /from\s*['"]dsh-context-compression-improved-runtime/u, label: 'cross-package runtime import' },
|
|
156
170
|
]
|
|
157
171
|
|
|
158
|
-
const walk = async (directory
|
|
172
|
+
const walk = async (directory) => {
|
|
159
173
|
const entries = await readdir(directory, { withFileTypes: true })
|
|
160
|
-
const files
|
|
174
|
+
const files = []
|
|
161
175
|
for (const entry of entries) {
|
|
162
176
|
const path = join(directory, entry.name)
|
|
163
177
|
if (entry.isDirectory()) files.push(...await walk(path))
|
|
@@ -175,52 +189,15 @@ for (const sourceRoot of sourceRoots) {
|
|
|
175
189
|
}
|
|
176
190
|
}
|
|
177
191
|
|
|
178
|
-
const lib = join(
|
|
192
|
+
const lib = join(packageRoot, 'lib')
|
|
179
193
|
if (!(await stat(lib)).isDirectory()) fail(`${relative(root, lib)} is missing; run build first`)
|
|
180
194
|
for (const path of await walk(lib)) {
|
|
181
195
|
if (path.endsWith('.map')) fail(`${relative(root, path)} is a source map`)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
// installed entry crash at module-load time with ERR_MODULE_NOT_FOUND — the
|
|
188
|
-
// same failure class as a cross-package import, so it gets the same gate.
|
|
189
|
-
// Only the import graph is gated: build by-products nothing imports (for
|
|
190
|
-
// example lib/style.css, whose rules the client artifact already carries
|
|
191
|
-
// inline) are neither shipped nor required.
|
|
192
|
-
const libArtifacts = await walk(lib)
|
|
193
|
-
const libNames = new Set(libArtifacts.map(path => relative(lib, path).replaceAll('\\', '/')))
|
|
194
|
-
const libScripts = [...libNames].filter(name => name.endsWith('.js')).sort()
|
|
195
|
-
const libAllowedSuffixes = ((selectorPackage.files as unknown as string[]) ?? [])
|
|
196
|
-
.filter(pattern => pattern.startsWith('lib/'))
|
|
197
|
-
.map(pattern => pattern.slice(pattern.lastIndexOf('*') + 1))
|
|
198
|
-
if (libAllowedSuffixes.length === 0) fail('selector package files allowlist covers no lib artifact')
|
|
199
|
-
const isAllowed = (name: string) => libAllowedSuffixes.some(suffix => name.endsWith(suffix))
|
|
200
|
-
const importedArtifacts = new Set<string>()
|
|
201
|
-
for (const name of libScripts) {
|
|
202
|
-
const text = await readFile(join(lib, name), 'utf8')
|
|
203
|
-
for (const match of text.matchAll(/from\s*["'](\.\/[^"']+)["']/gu)) {
|
|
204
|
-
const target = match[1]!.slice(2)
|
|
205
|
-
if (!libNames.has(target)) fail(`lib/${name} imports missing artifact ${match[1]}`)
|
|
206
|
-
importedArtifacts.add(target)
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
for (const name of [...libScripts, ...importedArtifacts].sort()) {
|
|
210
|
-
if (!isAllowed(name)) fail(`lib/${name} is part of the load graph but the package files allowlist would drop it`)
|
|
211
|
-
}
|
|
212
|
-
let trackedLib: Set<string> | undefined
|
|
213
|
-
try {
|
|
214
|
-
trackedLib = new Set(execFileSync('git', ['ls-files', '--', 'packages/selector/lib'], { cwd: root, encoding: 'utf8' })
|
|
215
|
-
.split('\n').map(line => line.trim()).filter(Boolean))
|
|
216
|
-
} catch (cause: unknown) {
|
|
217
|
-
fail(`cannot read the tracked artifact list with git: ${(cause as Error).message}`)
|
|
218
|
-
}
|
|
219
|
-
if (trackedLib === undefined || trackedLib.size === 0) fail('git tracks no packages/selector/lib artifact; a git install would ship an unbuilt package')
|
|
220
|
-
for (const name of [...libScripts, ...importedArtifacts].sort()) {
|
|
221
|
-
const tracked = `packages/selector/lib/${name}`
|
|
222
|
-
if (!trackedLib!.has(tracked)) {
|
|
223
|
-
fail(`${tracked} is not committed; a git install would fetch an incomplete artifact graph`)
|
|
196
|
+
if (path.endsWith('.js')) {
|
|
197
|
+
const text = await readFile(path, 'utf8')
|
|
198
|
+
if (/from\s*["']dsh-context-compression-improved-runtime["']/u.test(text)) {
|
|
199
|
+
fail(`${relative(root, path)} still imports the removed runtime package`)
|
|
200
|
+
}
|
|
224
201
|
}
|
|
225
202
|
}
|
|
226
203
|
|
|
@@ -234,7 +211,7 @@ if (!clientArtifact.includes('data-plugin-css') || !clientArtifact.includes('doc
|
|
|
234
211
|
if (/^\s*(?:import|export)\s/mu.test(clientArtifact)) fail('client.js contains ESM syntax')
|
|
235
212
|
if (/(?:\/home\/|[A-Za-z]:\\Users\\)/u.test(clientArtifact)) fail('client.js contains a developer absolute path')
|
|
236
213
|
if (clientArtifact.includes('sourceMappingURL')) fail('client.js contains a source map reference')
|
|
237
|
-
const clientRequires = [...clientArtifact.matchAll(/require\("([^"]+)"\)/gu)].map(match => match[1]
|
|
214
|
+
const clientRequires = [...clientArtifact.matchAll(/require\("([^"]+)"\)/gu)].map(match => match[1])
|
|
238
215
|
const allowedClientRequires = new Set([
|
|
239
216
|
'react',
|
|
240
217
|
'react/jsx-runtime',
|
|
@@ -244,7 +221,7 @@ for (const dependency of clientRequires) {
|
|
|
244
221
|
if (!allowedClientRequires.has(dependency)) fail(`client.js has unexpected external dependency ${dependency}`)
|
|
245
222
|
}
|
|
246
223
|
|
|
247
|
-
const collectSpecs = async (directory
|
|
224
|
+
const collectSpecs = async (directory) => (await walk(directory))
|
|
248
225
|
.filter(path => /\.spec\.tsx?$/u.test(path))
|
|
249
226
|
.map(path => relative(root, path).replaceAll('\\', '/'))
|
|
250
227
|
.sort()
|
|
@@ -289,11 +266,10 @@ for (const path of [...runtimeSpecs, ...selectorSpecs]) {
|
|
|
289
266
|
}
|
|
290
267
|
}
|
|
291
268
|
|
|
292
|
-
const runtime = await import(new URL('../packages/selector/lib/pruner.js', import.meta.url)
|
|
293
|
-
const defaults = runtime.DEFAULT_CUSTOM_COMPRESSION_POLICY
|
|
294
|
-
if (
|
|
295
|
-
if (
|
|
296
|
-
|| (defaults?.tailTrim as Record<string, unknown>)?.enabled !== false) {
|
|
269
|
+
const runtime = await import(new URL('../packages/selector/lib/pruner.js', import.meta.url))
|
|
270
|
+
const defaults = runtime.DEFAULT_CUSTOM_COMPRESSION_POLICY
|
|
271
|
+
if (defaults?.history?.trigger !== 500_000) fail('Custom History default is not 500000')
|
|
272
|
+
if (defaults?.tailTrim?.trigger !== 700_000 || defaults?.tailTrim?.enabled !== false) {
|
|
297
273
|
fail('Custom TailTrim default is not disabled at 700000')
|
|
298
274
|
}
|
|
299
275
|
|
package/tests/TEST_INVENTORY.md
CHANGED
|
@@ -5,17 +5,16 @@ legacy-test allowlist.
|
|
|
5
5
|
|
|
6
6
|
## Root suite
|
|
7
7
|
|
|
8
|
-
- Runtime: `packages/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
every `*.host.spec.ts` under the `selector-host` project.
|
|
8
|
+
- Runtime: `packages/runtime/tests/**/*.spec.ts` under the `runtime` project.
|
|
9
|
+
- Selector Host: `cache-prefix-audit.spec.ts` plus every `*.host.spec.ts` under
|
|
10
|
+
the `selector-host` project.
|
|
12
11
|
- Selector client: every `*.client.spec.ts` or `*.client.spec.tsx` under the
|
|
13
12
|
`selector-client` project.
|
|
14
13
|
- Built browser artifact: `packages/selector/tests/built/client-artifact.spec.ts`
|
|
15
14
|
under the separate `vitest.built.config.ts` gate, after `pnpm build`.
|
|
16
15
|
|
|
17
|
-
The root `pnpm test`,
|
|
18
|
-
`pnpm test:built` are release gates. `scripts
|
|
16
|
+
The root `pnpm test`, both package-local `pnpm test` commands, and
|
|
17
|
+
`pnpm test:built` are release gates. `scripts/verify-release.mjs` compares the
|
|
19
18
|
checked-in spec inventory with these project rules so a new test cannot be
|
|
20
19
|
silently excluded.
|
|
21
20
|
|
|
@@ -37,6 +36,6 @@ Their supported behavior is covered by active public tests:
|
|
|
37
36
|
service identity: `packages/selector/tests/preset-overlay-loader.e2e.host.spec.ts`;
|
|
38
37
|
- package/export/tarball contract:
|
|
39
38
|
`packages/selector/tests/public/package-contract.client.spec.ts` and
|
|
40
|
-
`scripts
|
|
39
|
+
`scripts/packed-install-e2e.mjs`;
|
|
41
40
|
- profile and Custom editor behavior:
|
|
42
41
|
`packages/selector/tests/profiles.client.spec.tsx`.
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One-off baseline capture: freeze the resolvePolicy output for the pre-existing
|
|
3
|
-
* profiles (before 'tokenpilot-inspired' is added) into a JSON fixture used by
|
|
4
|
-
* tests/runtime/tokenpilot/profile-baseline.spec.ts as the backward-compat golden.
|
|
5
|
-
*
|
|
6
|
-
* Usage: node scripts-dist/capture-profile-baseline.js [baseline-file]
|
|
7
|
-
*/
|
|
8
|
-
import { writeFileSync } from 'node:fs'
|
|
9
|
-
import { createRequire } from 'node:module'
|
|
10
|
-
|
|
11
|
-
/** The slice of the built pruner entry this capture consumes. */
|
|
12
|
-
interface PrunerRuntime {
|
|
13
|
-
resolveConfig: (input: Record<string, unknown>) => Record<string, unknown>
|
|
14
|
-
resolvePolicy: (
|
|
15
|
-
config: Record<string, unknown>,
|
|
16
|
-
profile: string,
|
|
17
|
-
custom: unknown,
|
|
18
|
-
options: Record<string, unknown>,
|
|
19
|
-
) => Record<string, unknown>
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** One option matrix row. */
|
|
23
|
-
interface OptionCase {
|
|
24
|
-
label: string
|
|
25
|
-
options: Record<string, unknown>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** One custom-document matrix row. */
|
|
29
|
-
interface CustomDocCase {
|
|
30
|
-
label: string
|
|
31
|
-
custom: unknown
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** The fixture shape `profile-baseline.spec.ts` reads back. */
|
|
35
|
-
interface ProfileBaseline {
|
|
36
|
-
capturedAt: string
|
|
37
|
-
profiles: Record<string, Record<string, Record<string, unknown>>>
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const require = createRequire(import.meta.url)
|
|
41
|
-
const runtime = require('../packages/selector/lib/pruner.js') as PrunerRuntime
|
|
42
|
-
|
|
43
|
-
const OLD_PROFILES: readonly string[] = [
|
|
44
|
-
'off',
|
|
45
|
-
'native',
|
|
46
|
-
'balanced',
|
|
47
|
-
'cache-strict',
|
|
48
|
-
'savings',
|
|
49
|
-
'adaptive',
|
|
50
|
-
'custom',
|
|
51
|
-
]
|
|
52
|
-
const baseConfig = runtime.resolveConfig({})
|
|
53
|
-
const OPTION_CASES: readonly OptionCase[] = [
|
|
54
|
-
{ label: 'defaults', options: {} },
|
|
55
|
-
{ label: 'linkage', options: { contextWindowTokens: 128_000, autoCompactThresholdPercent: 80 } },
|
|
56
|
-
]
|
|
57
|
-
const CUSTOM_DOCS: readonly CustomDocCase[] = [
|
|
58
|
-
{ label: 'default-custom', custom: undefined },
|
|
59
|
-
]
|
|
60
|
-
|
|
61
|
-
const snapshot: ProfileBaseline = { capturedAt: 'pre-tokenpilot-inspired', profiles: {} }
|
|
62
|
-
for (const profile of OLD_PROFILES) {
|
|
63
|
-
const byCase: Record<string, Record<string, unknown>> = {}
|
|
64
|
-
snapshot.profiles[profile] = byCase
|
|
65
|
-
for (const optionCase of OPTION_CASES) {
|
|
66
|
-
for (const customCase of CUSTOM_DOCS) {
|
|
67
|
-
const key = `${optionCase.label}${customCase.label === 'default-custom' ? '' : `/${customCase.label}`}`
|
|
68
|
-
byCase[key] = runtime.resolvePolicy(
|
|
69
|
-
baseConfig,
|
|
70
|
-
profile,
|
|
71
|
-
customCase.custom,
|
|
72
|
-
optionCase.options,
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const out = process.argv[2] ?? 'packages/selector/tests/runtime/fixtures/profile-baseline.json'
|
|
79
|
-
writeFileSync(out, `${JSON.stringify(snapshot, null, 2)}\n`)
|
|
80
|
-
console.log(`baseline written: ${out}`)
|
package/tsconfig.scripts.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"allowImportingTsExtensions": false,
|
|
7
|
-
"rootDir": "scripts",
|
|
8
|
-
"outDir": "scripts-dist",
|
|
9
|
-
"noEmit": false,
|
|
10
|
-
"types": ["node"]
|
|
11
|
-
},
|
|
12
|
-
"include": ["scripts/**/*.ts"]
|
|
13
|
-
}
|
|
File without changes
|
|
File without changes
|