mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
docs: trim CoT leakage from post-purge prose
Remove dead design-session citations, change narration, indexical stamps, and review-adjacent justification found by the dsh-trim-cot-leakage recall batteries in prose that landed after the last purge. Bilingual README pairs are re-recorded.
This commit is contained in:
@@ -92,8 +92,8 @@ describe('web e2e: agent-preset authoring is a host-side copy', () => {
|
||||
const snapshot = await captureStableAria(page, '[role="dialog"]', scaffold.workspaceCwd)
|
||||
|
||||
await compareOrRefreshGolden(SECTION_EXPECTED, snapshot, MODE)
|
||||
// The intro carries the guidance a create button used to imply, and the
|
||||
// shipped rows offer view/copy but never delete or a location — their
|
||||
// The intro states the copy path directly, and the shipped rows offer
|
||||
// view/copy but never delete or a location — their
|
||||
// install is overwritten by upgrades and is not the user's to manage.
|
||||
expect(snapshot).toContain('或用「创造模式」让 Agent 帮你创建')
|
||||
expect(snapshot).not.toContain('新建预设')
|
||||
|
||||
@@ -52,8 +52,8 @@ describe.skipIf(MODE === 'record')('web e2e: another usable provider ends first-
|
||||
await page.getByRole('button', { name: '设置', exact: true }).click()
|
||||
const settings = page.getByRole('dialog', { name: '设置' })
|
||||
await settings.waitFor({ timeout: 10_000 })
|
||||
// The onboarding step no longer navigates into Settings on dismissal, so
|
||||
// enter the Models section explicitly before exercising its normal cards.
|
||||
// Dismissing the onboarding step leaves Settings closed, so enter the
|
||||
// Models section explicitly before exercising its normal cards.
|
||||
await settings.getByRole('button', { name: '模型' }).click()
|
||||
const setupKey = settings.getByRole('textbox', { name: 'API 密钥', exact: true })
|
||||
await setupKey.waitFor({ timeout: 10_000 })
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
* published tarball has the same integrity is skipped, and a version whose
|
||||
* published tarball differs fails the run — that last case means the content
|
||||
* changed without a version bump. Skipping on identical integrity is what makes
|
||||
* re-running the publish step over the same artifact safe, which matters here
|
||||
* because a partial publication used to leave no way forward: republishing an
|
||||
* re-running the publish step over the same artifact safe. Without the
|
||||
* integrity skip, a partial publication has no way forward: republishing an
|
||||
* existing version fails permanently.
|
||||
*
|
||||
* Usage: `node scripts/publish-release.mjs [packed dir]`.
|
||||
|
||||
@@ -808,8 +808,8 @@ describe('hand-declared providers', () => {
|
||||
})
|
||||
|
||||
it('names the provider as the refreshed directory reports it after a rename', async () => {
|
||||
// The status line used to echo the target captured when the card opened,
|
||||
// which never lied while the name could not change. It can now.
|
||||
// A name can change after the card opens, so the saved status reads the
|
||||
// refreshed directory name rather than the target captured at open.
|
||||
const { face } = await mountSection({
|
||||
providers: { 'acme-gateway': { displayName: 'Acme Gateway', api: 'openai-completions' } },
|
||||
declaredRoutes: ['acme-gateway'],
|
||||
|
||||
@@ -69,8 +69,9 @@ describe('tool-call-model', () => {
|
||||
expect(model.title).toBe('Tool call')
|
||||
})
|
||||
|
||||
it('has dropped the v2 mount verbs that no longer exist', () => {
|
||||
// Keeping them would be a mapping for a tool nothing can call.
|
||||
it('renders v2 mount verbs with no current tool as generic calls', () => {
|
||||
// No current tool implements these v2 verbs, so a mapping would be
|
||||
// unreachable.
|
||||
expect(classifyTool('cordis_mount')).toBe('others')
|
||||
expect(toolRowModel('cordis_mount', running({ name: 'cordis_mount', argsRaw: '{}' })).title).toBe('Tool call')
|
||||
expect(toolRowModel('cordis_unmount', running({ name: 'cordis_unmount', argsRaw: '{}' })).title).toBe('Tool call')
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
折叠搜索是视图和添加操作旁的一枚区头按钮。在轨道中,添加和搜索会渲染为沿外壳共用横向进入路径移动的 36px 控件。激活搜索后,输入框会扩展并占据区头;点击外部只会收起经清除首尾空白后为空的查询——但轨道搜索手势仍在进行期间(直至列滑动结束、焦点落入输入框)除外,这样触发展开的那次点击不会收起它刚打开的搜索——而清除控件总会重置并收起搜索。非空白查询会以单一扁平结果列表替代任一浏览模式:不区分大小写的标题和 Workspace 子串匹配项会立即显示,经 250 ms 防抖的 Host 请求则会加入经过排序的当前对话内容匹配项及其摘要片段。英文搜索输入框及其防御性请求路径会移除 NUL,将查询限制在传输 schema 规定的 500 个 UTF-16 代码单元内且不会拆分代理项对,并保留现有的防抖与取消行为。每次新查询都会中止前一个请求;内容搜索失败时,元数据匹配项仍会显示,同时给出警告。列表最多显示 20 条结果,并会在查询过宽时提示用户缩小范围;打开所选 Session 时既不会清除查询,也不会跳转至特定事件。
|
||||
|
||||
该选择器通过全局 `useWorkspaces` hook 列出真实的 Host Workspace 实体。选择 Workspace 会调用 slot owner 的 `onPick` 回调,重新定位前端 Session 对象。不同的规范化路径即使 basename 和显示标题相同,仍会作为由 id 区分的独立 Workspace;侧边栏的悬停详情把 POSIX 家目录及其后代显示为 `~`/`~/…`,Windows 路径保持原样。每个注册各自声明一个**目录流子 slot**(`single` kind:`conversation.hero.workspace.directoryFlow`/`sidebar.workspaces.directoryFlow`),由组合的选择器包 client half 填入其选取交互——标准组合使用 [`-native`](../../host/directory-picker-native/README.zh.md) 后端的无渲染 OS 选择器驱动,`-browse` 组合下则是应用内浏览对话框。平铺显示的 **添加工作区…** 操作仅在当前界面的 slot 被占用时渲染(每次菜单渲染读取占用状态;slot 为空意味着该组合没有目录选择能力——seam 文档化的无流程默认行为,此时侧边栏区头直接不渲染添加按钮,而非留下一个点了没反应的按钮)。本包持有触发与接纳:占用方通过 slot 的属主交互约定(`open`/`busy`/`onPicked`/`onCancel`/`onError`)每次打开上报一个所选路径,owner 通过对象层接纳它,并等待 Workspace 列表投影刷新后才选中已提交的 Workspace;取消操作不会显示提示,错误落入可重试的文件夹对话框,其 **重新选择** 会重新打开流程。添加只有一条路径:占用者自带的新建文件夹能力已经覆盖了全新目录,因此不再单设按名称创建的对话框。菜单只在确有多个目标可选时出现——没有 Workspace 可列时,锚点手势直接拉起流程,而不是弹出只有一行的浮层;在列表基线落地前,空列表不算最终结果。运行时 Session 与 Workspace 服务负责物化。Workspace 行内的 Delete 操作会打开确认框,说明保留边界、阻止重复提交,并在失败时保持打开;成功后,该分组会被移除,其 Session 则留在 Ungrouped 下。Session 行内的 Rename 操作打开同款浏览器持有的对话框,并以该行的显示标题预填:客户端不设名称冲突规则(host 负责规范化,可能以 `title-invalid` 拒绝,错误渲染在对话框告警区);确认未修改的标题是有意允许的——这正是把当前自动标题钉住、不再被重新生成覆盖的手势。Session 行内的 Archive 操作不经确认对话框直接提交(非破坏性:日志和 workspace 记账席位保持不变),通过 `ctx.workspaces.archiveSession` 归档;归档集合回声落地后,该行从所有分组视图——workspace 分组、Ungrouped、内容搜索和平铺列表——中消失,失败只作为控制台诊断输出,树保持不变。空白的「新会话」行只是占位符:不渲染行菜单和时间标签(其中还没有发生任何事),重命名、fork 和归档都从首条提示词落地后才可用。
|
||||
该选择器通过全局 `useWorkspaces` hook 列出真实的 Host Workspace 实体。选择 Workspace 会调用 slot owner 的 `onPick` 回调,重新定位前端 Session 对象。不同的规范化路径即使 basename 和显示标题相同,仍会作为由 id 区分的独立 Workspace;侧边栏的悬停详情把 POSIX 家目录及其后代显示为 `~`/`~/…`,Windows 路径保持原样。每个注册各自声明一个**目录流子 slot**(`single` kind:`conversation.hero.workspace.directoryFlow`/`sidebar.workspaces.directoryFlow`),由组合的选择器包 client half 填入其选取交互——标准组合使用 [`-native`](../../host/directory-picker-native/README.zh.md) 后端的无渲染 OS 选择器驱动,`-browse` 组合下则是应用内浏览对话框。平铺显示的 **添加工作区…** 操作仅在当前界面的 slot 被占用时渲染(每次菜单渲染读取占用状态;slot 为空意味着该组合没有目录选择能力——seam 文档化的无流程默认行为,此时侧边栏区头直接不渲染添加按钮,而非留下一个点了没反应的按钮)。本包持有触发与接纳:占用方通过 slot 的属主交互约定(`open`/`busy`/`onPicked`/`onCancel`/`onError`)每次打开上报一个所选路径,owner 通过对象层接纳它,并等待 Workspace 列表投影刷新后才选中已提交的 Workspace;取消操作不会显示提示,错误落入可重试的文件夹对话框,其 **重新选择** 会重新打开流程。添加只有一条路径:占用者自带的新建文件夹能力已经覆盖了全新目录,因此不设独立的按名称创建对话框。菜单只在确有多个目标可选时出现——没有 Workspace 可列时,锚点手势直接拉起流程,而不是弹出只有一行的浮层;在列表基线落地前,空列表不算最终结果。运行时 Session 与 Workspace 服务负责物化。Workspace 行内的 Delete 操作会打开确认框,说明保留边界、阻止重复提交,并在失败时保持打开;成功后,该分组会被移除,其 Session 则留在 Ungrouped 下。Session 行内的 Rename 操作打开同款浏览器持有的对话框,并以该行的显示标题预填:客户端不设名称冲突规则(host 负责规范化,可能以 `title-invalid` 拒绝,错误渲染在对话框告警区);确认未修改的标题是有意允许的——这正是把当前自动标题钉住、使其不被重新生成覆盖的手势。Session 行内的 Archive 操作不经确认对话框直接提交(非破坏性:日志和 workspace 记账席位保持不变),通过 `ctx.workspaces.archiveSession` 归档;归档集合回声落地后,该行从所有分组视图——workspace 分组、Ungrouped、内容搜索和平铺列表——中消失,失败只作为控制台诊断输出,树保持不变。空白的「新会话」行只是占位符:不渲染行菜单和时间标签(其中还没有发生任何事),重命名、fork 和归档都从首条提示词落地后才可用。 (docs: trim CoT leakage from post-purge prose)
|
||||
|
||||
Workspace 和 Session 悬浮卡片会复制对应行被截断的值:激活 Workspace 卡片会写入其完整目录路径,激活非空白 Session 卡片则会写入其完整显示标题。临时的空白「新会话」卡片保持只读,因为其本地化标签是占位文案,并非会话内容。只有浏览器接受剪贴板写入后,卡片才会显示由字典提供的已复制状态。
|
||||
|
||||
|
||||
@@ -4,12 +4,9 @@
|
||||
* product.
|
||||
*
|
||||
* pnpm creates a workspace package's bin link only when the link target exists
|
||||
* at install time. Pointing the bin straight at `lib/bin.js` — a build product —
|
||||
* left the link uncreated on every clean checkout, so the command was missing
|
||||
* from `node_modules/.bin` even after a build produced the file, and only an
|
||||
* install that happened to follow a build brought it back. This file is
|
||||
* committed, so the link is always created; the build product is resolved when
|
||||
* the command actually runs.
|
||||
* at install time. `lib/bin.js` is a build product and is absent on a clean
|
||||
* checkout, so this committed file is the link target; it forwards to the build
|
||||
* product when the command runs.
|
||||
* @module @deepseek-ai/dsh-experimental-webworker-packer/bin
|
||||
*/
|
||||
import { existsSync } from 'node:fs'
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
* answers `/`, the directory that actually holds the entry. Node's three are
|
||||
* purely lexical and answer `/a/b`. A `node:path` proxy owes callers Node's
|
||||
* literal answers, so it needs its own port of Node's implementation rather than
|
||||
* a facade over this module (`apps/web-preview` keeps one; the divergence covers
|
||||
* 45 of ~200 cases, all in these three functions).
|
||||
* a facade over this module; the divergence covers 45 of ~200 cases, all in
|
||||
* these three functions, and `../../tests/node/path-diff.spec.ts` enumerates
|
||||
* them.
|
||||
* @module @deepseek-ai/dsh-experimental-webworker-runtime/src/module-system/posix-path
|
||||
*/
|
||||
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@
|
||||
* `node:path` for the worker: the POSIX algorithm, transliterated from Node's
|
||||
* implementation. It is NOT a face over the worker host's `posixPath`: that helper
|
||||
* normalizes before splitting, so `dirname('/a/b/..')` answers `/` where Node
|
||||
* answers `/a/b` (45 cases diverge — `.artifacts/p2/path-diff.ts` enumerates them).
|
||||
* answers `/a/b` (45 cases diverge; `../../../../tests/node/path-diff.spec.ts`
|
||||
* enumerates them).
|
||||
* A `node:` proxy has to answer what Node answers, since VFS paths were built with
|
||||
* Node semantics. `win32` members throw: the worker host reports
|
||||
* `process.platform === 'linux'`, so a Windows branch means a bug.
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* `node:worker_threads` stub. Nested workers are out of scope for v1, so the
|
||||
* workflow and code-runtime plugin bodies mount and fail on use. The
|
||||
* `node:worker_threads` stub. Nested workers are unsupported, so the workflow
|
||||
* and code-runtime plugin bodies mount and fail on use. The
|
||||
* thread-identity values are real: they say "this is the main thread", which is
|
||||
* what the worker host is from the tree's point of view.
|
||||
*/
|
||||
|
||||
@@ -9,30 +9,10 @@
|
||||
* emits, so a rolldown upgrade that starts emitting an unseen module form shows
|
||||
* up here first.
|
||||
*
|
||||
* Consolidated from `.artifacts/w0-lexer-probe.ts` (part 2). Two deliberate
|
||||
* changes for the terminal form:
|
||||
*
|
||||
* 1. **No `es-module-lexer`.** The lexer was retired as a runtime dependency
|
||||
* when the single acorn pass replaced the two-pass pipeline, so the
|
||||
* statistics it used to contribute are counted from the acorn AST instead.
|
||||
* The probe's part 1 (lexer field semantics over 20 sample forms) is dropped
|
||||
* entirely: it documented the behaviour of a component that no longer runs.
|
||||
* The forms themselves are covered as emitted-code assertions in
|
||||
* `transform-check.ts`.
|
||||
* 2. **The baseline exemptions are a pinned list, not a count.** Four files
|
||||
* cannot be imported by Node in this repository for reasons unrelated to the
|
||||
* transform; the probe merely counted them, so a fifth would have gone
|
||||
* unnoticed. Here they are named, and an unexpected member fails the run.
|
||||
*
|
||||
* Not consolidated: `.artifacts/v3-oracle.ts`, the byte-for-byte comparison
|
||||
* against the retired lexer pipeline. It was a **retirement gate** and it has
|
||||
* been through (`files=228 residualDifferences=0 lineDrift=0`). Keeping it as a
|
||||
* standing check would mean keeping two abandoned implementations alive
|
||||
* (`.artifacts/oracle-esm-to-cjs.ts`, `.artifacts/oracle-rewrite-await.ts`)
|
||||
* forever to compare against. The one real defect it caught that no other signal
|
||||
* could — `new.target` is also a `MetaProperty` — is preserved as a direct
|
||||
* assertion (`transform-check.ts`, trap 8), which is where that knowledge
|
||||
* belongs now.
|
||||
* Module-syntax statistics are counted from the acorn AST, so the check has no
|
||||
* separate lexer dependency. Baseline exemptions are a pinned list, not a count:
|
||||
* four files cannot be imported by Node in this repository for reasons unrelated
|
||||
* to the transform, and an unexpected member fails the run.
|
||||
*
|
||||
* Cost: this walks the whole build output and imports every bundle, so it takes
|
||||
* tens of seconds and needs `pnpm run build:lib:host` to have run. It is a
|
||||
@@ -275,7 +255,7 @@ async function runTransformed(code: string, path: string): Promise<Record<string
|
||||
return exports
|
||||
}
|
||||
|
||||
/** Module-syntax counts read from the AST, replacing what the retired lexer reported. */
|
||||
/** Module-syntax counts read from the AST. */
|
||||
interface Counts {
|
||||
staticImports: number
|
||||
dynamicImports: number
|
||||
@@ -369,7 +349,7 @@ if (files.length === 0) {
|
||||
|
||||
// The debugging contract, over the whole corpus: a transformed body has the
|
||||
// same line count as its source, so a stack frame still points at the right
|
||||
// line. This is the property the retired oracle measured as "line drift".
|
||||
// line.
|
||||
const sourceLines = source.split('\n').length
|
||||
const codeLines = code.split('\n').length
|
||||
if (sourceLines !== codeLines) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Semantic check of the worker module transform (`src/compile/transform.ts`): what the
|
||||
* emitted CommonJS body looks like for each module form, how suspension points
|
||||
* are rewritten, that line numbers survive, which forms are refused, and that
|
||||
* every trap the retired lexer pipeline hit stays fixed.
|
||||
* every covered trap form stays fixed.
|
||||
*
|
||||
* Scope boundary: this file checks the transform itself; the image collector's
|
||||
* loop around it is covered by the packer's `transform-image.spec.ts`.
|
||||
@@ -12,9 +12,10 @@
|
||||
* one — the code parses as script, publishes the right bindings, keeps line
|
||||
* count, and routes suspension through `__als`.
|
||||
*
|
||||
* The trap cases are the module forms that broke real boots under the retired
|
||||
* lexer pipeline. Five cannot recur under an AST pass, but retaining them pins
|
||||
* the behavior against a future parser swap.
|
||||
* The trap cases are module forms that break a boot when the transform
|
||||
* mishandles them. Five traps cannot recur while the AST pass is the parser,
|
||||
* but they stay checked because a future parser swap would reintroduce exactly
|
||||
* them.
|
||||
*/
|
||||
import { expect, test } from 'vitest'
|
||||
import { parse } from 'acorn'
|
||||
@@ -208,7 +209,7 @@ check(
|
||||
|
||||
{
|
||||
// Local exports are getters, so a later assignment is observable through
|
||||
// `exports` — the ESM live-binding property the report calls out explicitly.
|
||||
// `exports` — the ESM live-binding property.
|
||||
const code = transformModule('export let counter = 0\nexport function bump() { counter += 1 }\n', 'probe.js')
|
||||
parsesAsScript('live binding', code)
|
||||
const exports = runBody(code)
|
||||
@@ -224,9 +225,7 @@ check(
|
||||
}
|
||||
|
||||
{
|
||||
// Trap 4 in the lexer report: `export const a = 1, b = 2` reported only the
|
||||
// first declarator, so the AST pass upgraded this from "loud refusal" to
|
||||
// "correctly supported". Both bindings must appear.
|
||||
// Trap 4: a multi-declarator export publishes every binding.
|
||||
const code = transformModule('export const a = 1, b = 2\n', 'probe.js')
|
||||
parsesAsScript('multi-declarator export', code)
|
||||
const exports = runBody(code)
|
||||
@@ -415,7 +414,7 @@ function recordingAls(): { als: Record<string, unknown>; calls: string[] } {
|
||||
|
||||
{
|
||||
// for-await desugars to an explicit loop; `return()` must run only on abrupt
|
||||
// completion, which is the language rule the report calls out. The two
|
||||
// completion, which is the language rule. The two
|
||||
// completion paths need two different loop bodies, so they are separate cases.
|
||||
const plain = 'export const run = async (src) => { const seen = []\n'
|
||||
+ 'for await (const item of src) { seen.push(item) }\n'
|
||||
@@ -594,24 +593,24 @@ refuses('unparseable source is refused', 'export const = \n', 'parse failed')
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 9. Trap regressions. Each case broke a real boot under the retired lexer
|
||||
// pipeline; the AST pass must keep them fixed.
|
||||
// 9. Trap regressions. Each case is a module form that breaks a boot when the
|
||||
// transform mishandles it; the AST pass must keep them fixed.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
{
|
||||
// Trap 1: a file with no module syntax can still contain a dynamic import.
|
||||
// Early-returning on "no module syntax" left it unrewritten and it escaped to
|
||||
// the host engine's parser.
|
||||
// Trap 1: a file with no module syntax can still contain a dynamic import. A
|
||||
// transform that skips such files would leave it unrewritten, and it would
|
||||
// escape to the host engine's parser.
|
||||
const code = transformModule("module.exports = () => import('./x.js')\n", 'probe.js')
|
||||
contains('trap 1: dynamic import in a CommonJS file is still rewritten', code, '__dsh$dynImport')
|
||||
parsesAsScript('trap 1', code)
|
||||
}
|
||||
|
||||
{
|
||||
// Trap 2: `export {}` is a bundler module marker. The lexer reported nothing
|
||||
// for it, so it survived into `new Function` as `Unexpected token 'export'`.
|
||||
// The needle is the keyword in statement position, since `exports.` in the
|
||||
// prologue legitimately contains the same letters.
|
||||
// Trap 2: `export {}` is a bundler module marker and must be removed before
|
||||
// `new Function` parses the body. The needle is the keyword in statement
|
||||
// position, since `exports.` in the prologue legitimately contains the same
|
||||
// letters.
|
||||
const code = transformModule('export {};\n', 'probe.js')
|
||||
lacks('trap 2: bare export {} is removed', code, 'export {')
|
||||
lacks('trap 2: no export keyword survives', code, 'export;')
|
||||
@@ -630,10 +629,10 @@ refuses('unparseable source is refused', 'export const = \n', 'parse failed')
|
||||
}
|
||||
|
||||
{
|
||||
// Trap 6, the most costly one: a block comment before a class member named
|
||||
// `import` made the lexer report a dynamic import, renaming
|
||||
// `EntryTree.prototype.import` and breaking the loading chain at
|
||||
// `Entry._init` with "this.parent.tree.import is not a function".
|
||||
// Trap 6: a block comment before a class member named `import` must not be
|
||||
// treated as a dynamic import. Renaming `EntryTree.prototype.import` breaks
|
||||
// the loading chain at `Entry._init` with
|
||||
// "this.parent.tree.import is not a function".
|
||||
const source = 'export class A {\n /** doc */ import(name) { return name }\n}\n'
|
||||
const code = transformModule(source, 'probe.js')
|
||||
lacks('trap 6: a method named import is not rewritten', code, '__dsh$dynImport')
|
||||
@@ -643,19 +642,19 @@ refuses('unparseable source is refused', 'export const = \n', 'parse failed')
|
||||
}
|
||||
|
||||
{
|
||||
// Trap 7: a comment between `export` and the declaration keyword made the
|
||||
// gap-matching regex miss, refusing zod's `export /*@__NO_SIDE_EFFECTS__*/ function`
|
||||
// and taking 30-odd roster rows down with it.
|
||||
// Trap 7: a comment between `export` and the declaration keyword must not
|
||||
// hide the declaration; refusing zod's
|
||||
// `export /*@__NO_SIDE_EFFECTS__*/ function` takes 30-odd roster rows down
|
||||
// with it.
|
||||
const code = transformModule('export /*@__NO_SIDE_EFFECTS__*/ function $constructor(x) { return x }\n', 'probe.js')
|
||||
parsesAsScript('trap 7', code)
|
||||
check('trap 7: export with an interposed comment still publishes', typeof runBody(code).$constructor, 'function')
|
||||
}
|
||||
|
||||
{
|
||||
// The trap the AST pass introduced and the byte-level oracle caught:
|
||||
// `new.target` is also a MetaProperty. Replacing every MetaProperty made
|
||||
// `new.target === Cls` permanently false, silently disabling abstract-seam
|
||||
// guards in `jobs` and `llm`.
|
||||
// `new.target` is also a MetaProperty. Replacing every MetaProperty would
|
||||
// make `new.target === Cls` permanently false, silently disabling
|
||||
// abstract-seam guards in `jobs` and `llm`.
|
||||
const source = 'export class Base {\n constructor() { this.direct = new.target === Base }\n}\n'
|
||||
const code = transformModule(source, 'probe.js')
|
||||
contains('trap 8: new.target survives verbatim', code, 'new.target')
|
||||
@@ -668,9 +667,9 @@ refuses('unparseable source is refused', 'export const = \n', 'parse failed')
|
||||
}
|
||||
|
||||
{
|
||||
// Shebang handling (found while packing `yaml/bin.mjs`): `#!` is only legal at
|
||||
// offset 0, which the prologue occupies. It is commented out in place so both
|
||||
// offsets and the line count stay put.
|
||||
// Shebang handling: `#!` is only legal at offset 0, which the prologue
|
||||
// occupies. It is commented out in place so both offsets and the line count
|
||||
// stay put.
|
||||
const source = '#!/usr/bin/env node\nexport const main = 1\n'
|
||||
const code = transformModule(source, 'probe.js')
|
||||
lacks('shebang is not left in the emitted body', code, '#!')
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
* Cordis's `LoggerService` accepts every message and, with no exporter mounted,
|
||||
* only fills a ring buffer. No profile in this repository mounts one, so a
|
||||
* provider that fails and is skipped — the skill registry logs exactly that —
|
||||
* used to look identical to one that found nothing. That is how an empty skill
|
||||
* catalog hid a filesystem fault through two rounds of diagnosis, so the sink is
|
||||
* exercised here rather than trusted: a diagnostic nothing runs is a diagnostic
|
||||
* that silently stops working.
|
||||
* is indistinguishable from one that found nothing. The sink is exercised here
|
||||
* rather than trusted: a diagnostic that runs nothing is a diagnostic that
|
||||
* silently stops working.
|
||||
*/
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { installLogSink, type LogExporter, type LogMessage } from '../src/worker-host.ts'
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/**
|
||||
* The `node:child_process` face over the in-worker shell, and the ladder above
|
||||
* it: the REAL local subprocess service, running unmodified against this
|
||||
* module instead of a host kernel. That ladder is what the bash tool walks in
|
||||
* the browser, so proving it here is what makes the browser probe a
|
||||
* confirmation rather than the only evidence.
|
||||
* module instead of a host kernel. The bash tool walks this same ladder in the
|
||||
* browser.
|
||||
*
|
||||
* A Node test host has no DOM `Worker`, so the commands here run through the
|
||||
* inline strategy; the worker strategy and its frames are proven in
|
||||
* `../shell/shell-process.spec.ts`, and both meet again in the preview probe.
|
||||
* `../shell/shell-process.spec.ts`.
|
||||
*
|
||||
* `process.kill` is redirected to the worker's process table for the same
|
||||
* reason the worker does it: the subprocess service polls process-group
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
* `node:path/posix`", so Node itself is the oracle and every case is compared
|
||||
* rather than asserted against a hand-written expectation. The corpus is the
|
||||
* shapes a VFS path actually takes (absolute image paths, `node_modules`
|
||||
* specifiers, `.bin` entries) plus the edge forms that historically diverge
|
||||
* (repeated slashes, trailing dots, `..` past the root).
|
||||
* specifiers, `.bin` entries) plus the edge forms that diverge between the two
|
||||
* implementations (repeated slashes, trailing dots, `..` past the root).
|
||||
*
|
||||
* Migrated from apps/web-preview/scripts/checks/path-diff.ts. Imports go through
|
||||
* the package name so the harness and the shim resolve to one module instance
|
||||
* (see `../polyfill/als-shim.spec.ts` for why that matters).
|
||||
* Imports go through the package name so the harness and the shim resolve to one
|
||||
* module instance (see `../polyfill/als-shim.spec.ts` for why that matters).
|
||||
*/
|
||||
import { expect, test } from 'vitest'
|
||||
import { posix as nodePosix } from 'node:path'
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
* - both completion paths do this, which is why the token always fulfills.
|
||||
*
|
||||
* The shim-backed end of the same contract (does a real AsyncLocalStorage
|
||||
* actually fold, do the hooks cover timers) is `als-shim.spec.ts`, and the
|
||||
* cross-session behavioural proof is the browser concurrency probe. This file is
|
||||
* actually fold, do the hooks cover timers) is `als-shim.spec.ts`. This file is
|
||||
* the middle layer: the protocol, in isolation.
|
||||
*/
|
||||
import { expect, test } from 'vitest'
|
||||
@@ -121,8 +120,8 @@ function recordingCausality(): {
|
||||
}
|
||||
|
||||
{
|
||||
// The rejection path restores too, and only then rethrows: a catch clause must
|
||||
// observe the caller's store, which is the case the browser probe pinned.
|
||||
// The rejection path restores too, and only then rethrows: a catch clause
|
||||
// must observe the caller's store.
|
||||
const state = recordingCausality()
|
||||
const als = createAlsRuntime(state.causality)
|
||||
state.current = 'session-C'
|
||||
@@ -310,9 +309,9 @@ function recordingCausality(): {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 6. The inert runtime. `?als=inert` is the browser probe's control arm: the
|
||||
// rewrite still runs and still hops a microtask, but no state moves. That
|
||||
// control must be genuinely inert, or the probe loses its discriminating power.
|
||||
// 6. The inert runtime. Without a causality face, the rewrite still runs and
|
||||
// still hops a microtask, but no state moves. A comparison arm built on this
|
||||
// mode must be genuinely inert, or the comparison proves nothing.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
{
|
||||
|
||||
@@ -17,15 +17,11 @@
|
||||
*
|
||||
* Scope boundary: this file owns the shim (the state). `als-runtime.spec.ts`
|
||||
* owns the protocol that moves snapshots around, with the causality face stubbed.
|
||||
* The cross-session end-to-end proof is the browser concurrency probe, whose
|
||||
* control arm (`?als=inert`) relies on the protocol being genuinely inert.
|
||||
*
|
||||
* Migrated from apps/web-preview/scripts/checks/als-check.ts after the Node
|
||||
* compatibility layer was reorganized into implemented/mock/globals. Every import
|
||||
* goes through the **package name**, not a relative path: a check that reached
|
||||
* built `lib/` while the shim resolved by package name to `src/` produced two
|
||||
* module instances and a shim mounted in the wrong world (the `fs-check`
|
||||
* incident — "no filesystem is mounted"). One resolution path per module.
|
||||
* Every import goes through the **package name**, not a relative path: a check
|
||||
* that reaches built `lib/` while the shim resolves by package name to `src/`
|
||||
* gets two module instances and a shim mounted in the wrong world (the failure
|
||||
* mode asserted in `../node/fs.spec.ts`). One resolution path per module.
|
||||
*/
|
||||
import { expect, test } from 'vitest'
|
||||
import {
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
* (`runShellProcess`) against the REAL host half, so the frames, the
|
||||
* filesystem service, and the termination ladder are the shipped ones — only
|
||||
* the thread boundary is simulated, because a Node test host has no DOM
|
||||
* `Worker` to cross. That a browser worker really can start a nested worker
|
||||
* and terminate it mid-burn is measured separately, in the preview probe.
|
||||
* `Worker` to cross. The real browser Worker boundary is not exercised here.
|
||||
*/
|
||||
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
|
||||
import { MemoryVfs } from '@deepseek-ai/dsh-experimental-webworker-runtime/src/storage/memory.ts'
|
||||
|
||||
@@ -1032,8 +1032,8 @@ describe('compat switches', () => {
|
||||
})
|
||||
|
||||
it('refuses a compat key no wire protocol declares instead of dropping it', () => {
|
||||
// The silent drop is what let an unreadable switch look applied: schemastery
|
||||
// passes unknown keys through, and resolution used to read only two fields.
|
||||
// Schemastery passes unknown keys through, so silently dropping one would
|
||||
// make an unreadable switch look applied; the resolver must refuse it.
|
||||
expect(() => resolveProfiles({
|
||||
'acme-gateway': {
|
||||
api: 'openai-completions',
|
||||
|
||||
@@ -331,9 +331,9 @@ describe.skipIf(!isWin32 || !pwshAvailable())('windows-acl runner', () => {
|
||||
// workspace-write keeps the ACE standing for the server lifetime. After
|
||||
// switching to read-only, the restricted token's read-only list must carry NO
|
||||
// capability SID — the standing ACE stays but the pass-2 check cannot use
|
||||
// it, so the workspace write is denied (previously it LEAKED). The
|
||||
// switch back reuses the SAME standing ACE: the re-upgrade write lands
|
||||
// without any re-grant.
|
||||
// it, so the workspace write is denied instead of leaking through the
|
||||
// standing ACE. The switch back reuses the SAME standing ACE: the
|
||||
// re-upgrade write lands without any re-grant.
|
||||
const writeSid = workspaceWriteSid(writableDir)
|
||||
const privateTemp = join(isolatedTemp, 'mode-switch-temp')
|
||||
mkdirSync(privateTemp)
|
||||
|
||||
@@ -152,9 +152,9 @@ describe('SessionProjectionRegistry drive', () => {
|
||||
|
||||
first()
|
||||
|
||||
// The regression this counts against: one session ending used to strip
|
||||
// the projection from every other live session, because the first
|
||||
// registrant owned the only disposer.
|
||||
// The regression this counts against: without last-release semantics, one
|
||||
// session ending strips the projection from every other live session,
|
||||
// because the first registrant owns the only disposer.
|
||||
expect(ctx.sessionProjections.snapshot(session).values['test/marks']).toEqual({ marks: ['kept'] })
|
||||
second()
|
||||
expect(ctx.sessionProjections.snapshot(session).values).toEqual({})
|
||||
|
||||
Reference in New Issue
Block a user