diff --git a/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.i18n.yaml b/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.i18n.yaml new file mode 100644 index 0000000000..c4907f9030 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# side as of the last confirmed-consistent state. Both languages carry equal authority; +# after editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-09-05-package-manifest-types.md +2026-09-05-package-manifest-types.md: 94317a9317ba12059e726612840e4a001be2a892 +2026-09-05-package-manifest-types.zh.md: 2c40facd2591921123b5eae71b80c516f3b1f697 diff --git a/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.md b/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.md new file mode 100644 index 0000000000..94317a9317 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.md @@ -0,0 +1,31 @@ +# Agent Note: Package manifest declaration ownership + +Status: implemented + +English | [中文](2026-09-05-package-manifest-types.zh.md) + +## Problem + +External packages need Harness manifest types without depending on boot or client implementations. Keeping declarations beside individual readers obscures the complete configuration API and lets overlapping fields diverge. + +## Decision + +[`@deepseek-ai/dsh-package-manifest`](../../../../packages/util/package-manifest/README.md) owns `DshManifest` and its member declarations in one type-only file. The package belongs to the existing utility group and exports no runtime values. Author declarations and launcher-generated module fallback metadata are explicitly distinguished. + +Readers import the shared declarations directly. Boot retains profile loading, raw JSON checks, defaults, and resolved runtime data. Client modules retain their normalized boot graph. The image packer resolves declared paths into directories. The Session catalog generator derives a read-only validated entry with a resolved import path; raw inputs and discovery rules remain local. + +App-boot declares a production dependency because its published declarations reference the shared types. Client modules, the private packer, and root scripts use development dependencies because their published APIs do not expose these types. Every package consumer has a TypeScript project reference. External authors import from the utility package; app-boot provides no compatibility re-exports. + +## Alternatives considered + +**Keep declarations in individual readers.** External authors would depend on runtime implementations, and a partial profile-only definition would omit existing client and build fields. + +**Create a separate types group.** The existing utility group accommodates a type-only library without another package category. Runtime service and event declarations stay with their owners. + +**Unify the JSON parsers.** Sharing declarations does not require changing validation, errors, defaults, or parsed results; those remain owned by each reader. + +## Consequences + +Authors gain one public import path at the cost of a published package and explicit dependency edges. Existing app-boot manifest type imports must use the new package. The [profile composition design](2026-08-05-profile-plugin-bundles.md) continues to own runtime semantics; type extraction does not change configuration acceptance or model-visible behavior. + +Compiler and packaged NodeNext consumer checks cover public imports. Existing profile, client, image configuration, and Session catalog tests cover reader behavior; documentation checks cover the utility classification and generated package catalogs. Optional declaration fields still require deliberate consumer updates when added. diff --git a/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.zh.md b/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.zh.md new file mode 100644 index 0000000000..2c40facd25 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.zh.md @@ -0,0 +1,31 @@ +# Agent Note: Package manifest 声明归属 + +Status: implemented + +[English](2026-09-05-package-manifest-types.md) | 中文 + +## 问题 + +外部包需要 Harness manifest 类型,而无需依赖启动器或客户端实现。将声明放在各读取方旁边,会使完整配置 API 难以查找,也容易让重叠字段发生偏离。 + +## 决策 + +[`@deepseek-ai/dsh-package-manifest`](../../../../packages/util/package-manifest/README.zh.md) 在一个纯类型文件中拥有 `DshManifest` 及其成员声明。本包属于现有工具库分组,不导出运行时值。作者声明与启动器生成的模块后备元数据有明确区分。 + +各读取方直接导入共享声明。启动器保留 profile 加载、原始 JSON 检查、默认值和解析后的运行时数据。客户端模块保留归一化的启动图。镜像打包器将声明路径解析为目录。Session 目录生成器派生带有已解析导入路径的只读校验结果;原始输入和发现规则仍由本地负责。 + +App-boot 声明生产依赖,因为其发布的声明文件引用共享类型。客户端模块、私有打包器和根脚本使用开发依赖,因为其发布 API 不暴露这些类型。每个包消费方都有 TypeScript 项目引用。外部作者从工具包导入;app-boot 不提供兼容性再导出。 + +## 考虑过的替代方案 + +**将声明保留在各读取方。** 外部作者会依赖运行时实现,而仅覆盖 profile 的部分定义会遗漏已有的客户端和构建字段。 + +**创建独立的 types 分组。** 现有工具库分组可以容纳纯类型库,无需增加包分类。运行时服务和事件声明仍由各自负责方拥有。 + +**统一 JSON 解析器。** 共享声明不要求改变校验、错误、默认值或解析结果;这些仍由各读取方负责。 + +## 后果 + +作者获得统一的公共导入路径,代价是一个发布包和明确的依赖边。已有的 app-boot manifest 类型导入需要改用新包。[Profile 组合设计](2026-08-05-profile-plugin-bundles.zh.md) 继续负责运行时语义;类型提取不改变配置接受范围或模型可见行为。 + +编译器与打包后的 NodeNext 消费方检查覆盖公共导入。已有 profile、客户端、镜像配置和 Session 目录测试覆盖读取行为;文档检查覆盖工具库分类与生成的包目录。新增可选声明字段时,仍需主动更新消费方。 diff --git a/docs/config-catalog.i18n.yaml b/docs/config-catalog.i18n.yaml index 8ad7d6a459..3f87cb1fea 100644 --- a/docs/config-catalog.i18n.yaml +++ b/docs/config-catalog.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/config-catalog.md -config-catalog.md: 884a45b7e165329a5d9dd6470d29812d95fb1b62 -config-catalog.zh.md: e8586045fb8727ccbc604b5345f8c1cac54d40e7 +config-catalog.md: 66657ff6c3f5874a4922f26fd61c65ebb7f37826 +config-catalog.zh.md: 6ae44ca258720dd1a7aa567f0ed71e996410b9ea diff --git a/docs/config-catalog.md b/docs/config-catalog.md index 884a45b7e1..66657ff6c3 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -3468,6 +3468,7 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them. - `@deepseek-ai/dsh-loader-smoke` ([`packages/test-support/loader-smoke/src/index.ts`](../packages/test-support/loader-smoke/src/index.ts)) - `@deepseek-ai/dsh-native-command` ([`packages/util/native-command/src/index.ts`](../packages/util/native-command/src/index.ts)) - `@deepseek-ai/dsh-output-retention` ([`packages/util/output-retention/src/index.ts`](../packages/util/output-retention/src/index.ts)) +- `@deepseek-ai/dsh-package-manifest` ([`packages/util/package-manifest/src/index.ts`](../packages/util/package-manifest/src/index.ts)) - `@deepseek-ai/dsh-sandbox-windows-acl` ([`packages/sandbox/sandbox-windows-acl/src/index.ts`](../packages/sandbox/sandbox-windows-acl/src/index.ts)) - `@deepseek-ai/dsh-scope` ([`packages/core/scope/src/index.ts`](../packages/core/scope/src/index.ts)) - `@deepseek-ai/dsh-sdk-client` ([`packages/sdk/client/src/index.ts`](../packages/sdk/client/src/index.ts)) diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md index e8586045fb..6ae44ca258 100644 --- a/docs/config-catalog.zh.md +++ b/docs/config-catalog.zh.md @@ -3469,6 +3469,7 @@ export interface Config { - `@deepseek-ai/dsh-loader-smoke`([`packages/test-support/loader-smoke/src/index.ts`](../packages/test-support/loader-smoke/src/index.ts)) - `@deepseek-ai/dsh-native-command`([`packages/util/native-command/src/index.ts`](../packages/util/native-command/src/index.ts)) - `@deepseek-ai/dsh-output-retention`([`packages/util/output-retention/src/index.ts`](../packages/util/output-retention/src/index.ts)) +- `@deepseek-ai/dsh-package-manifest` ([`packages/util/package-manifest/src/index.ts`](../packages/util/package-manifest/src/index.ts)) - `@deepseek-ai/dsh-sandbox-windows-acl`([`packages/sandbox/sandbox-windows-acl/src/index.ts`](../packages/sandbox/sandbox-windows-acl/src/index.ts)) - `@deepseek-ai/dsh-scope`([`packages/core/scope/src/index.ts`](../packages/core/scope/src/index.ts)) - `@deepseek-ai/dsh-sdk-client`([`packages/sdk/client/src/index.ts`](../packages/sdk/client/src/index.ts)) diff --git a/docs/module-graph.i18n.yaml b/docs/module-graph.i18n.yaml index a84ece4a7f..fac4831da7 100644 --- a/docs/module-graph.i18n.yaml +++ b/docs/module-graph.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/module-graph.md -module-graph.md: be0bc1db1222ba7b95dff735a339bef680b86cf5 -module-graph.zh.md: e1fdaae73ac398076598316efcfa45822e378155 +module-graph.md: 5286f8729930be0abc4c5f11325c93408915b808 +module-graph.zh.md: 0a43108841558b68f376f6129b8f52b8bed2c244 diff --git a/docs/module-graph.md b/docs/module-graph.md index be0bc1db12..5286f87299 100644 --- a/docs/module-graph.md +++ b/docs/module-graph.md @@ -16,6 +16,7 @@ flowchart TD pkg_launch_environment["launch-environment"] pkg_native_command["native-command"] pkg_output_retention["output-retention"] + pkg_package_manifest["package-manifest"] pkg_timeout["timeout"] pkg_util_crypto["util-crypto"] pkg_util_time["util-time"] @@ -1162,6 +1163,7 @@ flowchart TD | [`launch-environment`](../packages/util/launch-environment) | `util` | — | | [`native-command`](../packages/util/native-command) | `util` | — | | [`output-retention`](../packages/util/output-retention) | `util` | — | +| [`package-manifest`](../packages/util/package-manifest) | `util` | — | | [`timeout`](../packages/util/timeout) | `util` | — | | [`util-crypto`](../packages/util/crypto) | `util` | — | | [`util-time`](../packages/util/time) | `util` | — | diff --git a/docs/module-graph.zh.md b/docs/module-graph.zh.md index e1fdaae73a..0a43108841 100644 --- a/docs/module-graph.zh.md +++ b/docs/module-graph.zh.md @@ -18,6 +18,7 @@ flowchart TD pkg_launch_environment["launch-environment"] pkg_native_command["native-command"] pkg_output_retention["output-retention"] + pkg_package_manifest["package-manifest"] pkg_timeout["timeout"] pkg_util_crypto["util-crypto"] pkg_util_time["util-time"] @@ -1164,6 +1165,7 @@ flowchart TD | [`launch-environment`](../packages/util/launch-environment) | `util` | — | | [`native-command`](../packages/util/native-command) | `util` | — | | [`output-retention`](../packages/util/output-retention) | `util` | — | +| [`package-manifest`](../packages/util/package-manifest) | `util` | — | | [`timeout`](../packages/util/timeout) | `util` | — | | [`util-crypto`](../packages/util/crypto) | `util` | — | | [`util-time`](../packages/util/time) | `util` | — | diff --git a/package.json b/package.json index 4ce55b55bd..e21bee27f2 100644 --- a/package.json +++ b/package.json @@ -161,6 +161,7 @@ "postinstall": "node scripts/install-lefthook.mjs" }, "devDependencies": { + "@deepseek-ai/dsh-package-manifest": "workspace:^", "@deepseek-ai/dsh-tool-session-query": "workspace:^", "@deepseek-ai/dsh-web-fetch-http": "workspace:^", "@stylistic/eslint-plugin": "^5.10.0", diff --git a/packages/boot/app-boot/README.i18n.yaml b/packages/boot/app-boot/README.i18n.yaml index aa898932cf..8a65f554d4 100644 --- a/packages/boot/app-boot/README.i18n.yaml +++ b/packages/boot/app-boot/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/boot/app-boot/README.md -README.md: ddbcc900fcbb38e83b35f517f9d38cf0e04927f3 -README.zh.md: 184e1a086d09bf6807fd8fb2d17f7157ba8deaa6 +README.md: 3ef00ac2e505751215da89295cfd6c6513dcf674 +README.zh.md: bf3e32641fe48229f61d0eeedbaf083aceb2b99e diff --git a/packages/boot/app-boot/README.md b/packages/boot/app-boot/README.md index ddbcc900fc..3ef00ac2e5 100644 --- a/packages/boot/app-boot/README.md +++ b/packages/boot/app-boot/README.md @@ -45,6 +45,8 @@ With that entry point, success looks like a running app with every plugin active ### Profiles +Import profile and bundle declaration types from [`@deepseek-ai/dsh-package-manifest`](../../util/package-manifest/README.md). App-boot owns profile loading, JSON validation, and resolved runtime data. + A profile is how one dsh installation ships different app surfaces: `web`, `headless`, `acp`, `sdk`, and `sdk-minimal` start distinct compositions from the same launcher. A profile lives at `$DSH_HOME/profiles/` and combines installable bundles, its own `cordis.patch.yml`, and `patchReload: live | startup`; omitted reload policy keeps the historical `live` default for custom profiles. The shipped `web` template uses live reload, while the other shipped templates apply patches only at startup. `sdk-minimal` names only its standalone bundle; the other templates retain base-plus-mode stacks. `dsh plugin` creates custom profiles, and a missing bundle or one without a patch declaration fails startup loudly. Your machine-local preferences also live in the Harness home: diff --git a/packages/boot/app-boot/README.zh.md b/packages/boot/app-boot/README.zh.md index 184e1a086d..bf3e32641f 100644 --- a/packages/boot/app-boot/README.zh.md +++ b/packages/boot/app-boot/README.zh.md @@ -45,6 +45,8 @@ const ctx = await boot('dsh', resolveConfigPath(argv[2], process.env.DSH_SNAPSHO ### Profile +Profile 与 bundle 的声明类型从 [`@deepseek-ai/dsh-package-manifest`](../../util/package-manifest/README.zh.md) 导入。App-boot 负责 profile 加载、JSON 校验和解析后的运行时数据。 + profile 是同一套 dsh 安装提供不同应用界面的方式:`web`、`headless`、`acp`、`sdk` 与 `sdk-minimal` 从同一 launcher 启动不同组合。profile 位于 `$DSH_HOME/profiles/`,由可安装 bundle、自身 `cordis.patch.yml` 与 `patchReload: live | startup` 组成;自定义 profile 省略 reload 策略时保留历史 `live` 默认值。随产品交付的 `web` 模板实时重载,其他随附模板只在启动时应用 patch。`sdk-minimal` 只列出自身的独立 bundle,其他模板保留 base 加模式 bundle 的栈。`dsh plugin` 创建自定义 profile;缺失 bundle 或未声明 patch 的 bundle 会让启动明确失败。 你的机器本地偏好同样位于 harness home 中: diff --git a/packages/boot/app-boot/package.json b/packages/boot/app-boot/package.json index ad104c9920..bfb9e205c0 100644 --- a/packages/boot/app-boot/package.json +++ b/packages/boot/app-boot/package.json @@ -28,6 +28,7 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-atomic-write": "workspace:^", + "@deepseek-ai/dsh-package-manifest": "workspace:^", "js-yaml": "^4.2.0", "resolve.exports": "^2.0.3" }, diff --git a/packages/boot/app-boot/src/index.ts b/packages/boot/app-boot/src/index.ts index 8059b4849c..4a88c63a0f 100644 --- a/packages/boot/app-boot/src/index.ts +++ b/packages/boot/app-boot/src/index.ts @@ -41,14 +41,10 @@ export { resolveBundleDir, resolveProfileDir, writeProfileManifest, - type DshBundleManifest, - type DshManifestSection, - type DshProfileManifest, type Profile, type ProfileLayer, type ProfileManifest, type ProfileModuleFallbackOptions, - type ProfilePatchReload, type ProfileTemplate, } from './profile.ts' diff --git a/packages/boot/app-boot/src/profile.ts b/packages/boot/app-boot/src/profile.ts index 52e8bcfafc..3c97bab40c 100644 --- a/packages/boot/app-boot/src/profile.ts +++ b/packages/boot/app-boot/src/profile.ts @@ -34,6 +34,7 @@ import { withFileLock } from '@deepseek-ai/dsh-atomic-write' import type { EntryOptions } from '@deepseek-ai/cordis-plugin-loader' import { applyEntryPatches, type PatchOptions } from '@deepseek-ai/cordis-plugin-include' import { resolveDshHome } from '@deepseek-ai/dsh-home-paths' +import type { DshManifest, DshModuleFallbackManifest, ProfilePatchReload } from '@deepseek-ai/dsh-package-manifest' import { resolve as resolvePackage, type Package as ResolvePackageManifest } from 'resolve.exports' import { loadOverlayPatches } from './index.ts' @@ -46,23 +47,6 @@ export const PROFILE_PATCH_FILENAME = 'cordis.patch.yml' /** Profile-private package links projected into its pnpm-managed node_modules. */ const PROFILE_MODULE_FALLBACK_DIR = '.dsh-module-fallback' -/** The bundle half of the `dsh` manifest section: what a bundle package exports. */ -export interface DshBundleManifest { - /** The patch layer this bundle exports, relative to its package root. */ - patch: string -} - -/** The profile half of the `dsh` manifest section: what a profile directory composes. */ -export interface DshProfileManifest { - /** Ordered bundle layer list (package names). */ - bundles?: string[] - /** Whether user patch files reload while this profile remains active. */ - patchReload?: ProfilePatchReload -} - -/** User patch-file lifecycle selected by a profile. */ -export type ProfilePatchReload = 'live' | 'startup' - /** Installation-owned defaults used when a shipped profile is first opened. */ export interface ProfileTemplate { /** Ordered bundle layer list. */ @@ -71,23 +55,12 @@ export interface ProfileTemplate { patchReload: ProfilePatchReload } -/** - * The profile-launcher slice of the `dsh`-owned package.json section. A - * manifest may declare both roles; other consumers own additional keys. - */ -export interface DshManifestSection { - /** Bundle metadata consumed by the profile launcher. */ - bundle?: DshBundleManifest - /** Profile metadata consumed by the profile launcher. */ - profile?: DshProfileManifest -} - /** The slice of package.json both profiles and bundles use. */ export interface ProfileManifest { name?: string dependencies?: Record peerDependencies?: Record - dsh?: DshManifestSection + dsh?: DshManifest } /** One resolved bundle layer of a profile. */ @@ -335,7 +308,7 @@ interface ModuleProxyManifest { private: true type: 'module' exports: Record - dsh: { moduleFallback: { targets: Record } } + dsh: { moduleFallback: DshModuleFallbackManifest } } interface ModuleProxyRecord { diff --git a/packages/boot/app-boot/tsconfig.json b/packages/boot/app-boot/tsconfig.json index bb1ce09d7b..39d572d19a 100644 --- a/packages/boot/app-boot/tsconfig.json +++ b/packages/boot/app-boot/tsconfig.json @@ -34,6 +34,9 @@ }, { "path": "../../util/home-paths" + }, + { + "path": "../../util/package-manifest" } ] } diff --git a/packages/client/modules/README.i18n.yaml b/packages/client/modules/README.i18n.yaml index 5b7a0a5b40..16df1c0dca 100644 --- a/packages/client/modules/README.i18n.yaml +++ b/packages/client/modules/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/client/modules/README.md -README.md: 414d34af202ee4ab24e1b7570697ad63bd8cdbc8 -README.zh.md: e6adc7b7d0265e52d5108e241a8f8a551976536d +README.md: 7bfa39d183bb29f3f9481bb39280c5521786031a +README.zh.md: 64dc5644f535722b464c867616b18ff557e921be diff --git a/packages/client/modules/README.md b/packages/client/modules/README.md index 414d34af20..7bfa39d183 100644 --- a/packages/client/modules/README.md +++ b/packages/client/modules/README.md @@ -25,6 +25,8 @@ English | [中文](README.zh.md) ## Use this package +Use [`DshClientManifest`](../../util/package-manifest/README.md) for the declaration type. Client-modules validates the JSON and owns the normalized boot graph. + Use it when you compose or build a browser client plugin: the package turns a package's `dsh.client` declaration into a loadable browser bundle with no per-plugin wiring. It activates with the web composition; the shell boots it before any plugin runs. ### Declaring a client plugin diff --git a/packages/client/modules/README.zh.md b/packages/client/modules/README.zh.md index e6adc7b7d0..64dc5644f5 100644 --- a/packages/client/modules/README.zh.md +++ b/packages/client/modules/README.zh.md @@ -25,6 +25,8 @@ kind: "package-reference" ## 使用本包 +声明类型使用 [`DshClientManifest`](../../util/package-manifest/README.zh.md)。Client-modules 负责 JSON 校验和归一化的启动图。 + 组合或构建浏览器客户端插件时使用它:本包把包的 `dsh.client` 声明变成可加载的浏览器 bundle,无需任何逐插件接线。它随 web 组合激活;外壳在任何插件运行前启动它。 ### 声明客户端插件 diff --git a/packages/client/modules/package.json b/packages/client/modules/package.json index 0fc07f2808..8d52321929 100644 --- a/packages/client/modules/package.json +++ b/packages/client/modules/package.json @@ -45,7 +45,8 @@ "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/dsh-package-manifest": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/modules/src/index.ts b/packages/client/modules/src/index.ts index 98b6fa5019..e8c6770c95 100644 --- a/packages/client/modules/src/index.ts +++ b/packages/client/modules/src/index.ts @@ -33,6 +33,7 @@ import { Service } from '@deepseek-ai/cordis' import type { Context } from '@deepseek-ai/cordis' import type { Entry } from '@deepseek-ai/cordis-plugin-loader' import type { IndexInjection } from '@deepseek-ai/dsh-host-webserver' +import type { DshClientManifest } from '@deepseek-ai/dsh-package-manifest' import { optionalStringArray, stripClientSuffix } from './client/manifest.ts' import type { WebBootBatch, WebBootBatchPhase, WebBootEntry, WebBootGraph } from './client/manifest.ts' @@ -48,22 +49,6 @@ declare module '@deepseek-ai/cordis' { } } -/** package.json `dsh.client` declaration fields, validated one by one after reading the file. */ -interface DshClientDeclaration { - inject?: string[] - platform: string - /** Boot phase-one registration barrier; absent rows still ride the shared application batch. */ - immediately?: boolean - /** - * Exact module-table requests beyond the implicit client baseline. Any - * specifier is valid, including subpaths such as `/client`; each - * importing package declares its own exceptional requests. A type-only - * import is not a request because the transform erases it before resolution. - * Absent means the package uses only the baseline externals. - */ - external?: string[] -} - /** The declared fields a graph row carries, normalized (absent array declarations become empty). */ interface WebBootRowFields { inject?: string[] @@ -198,7 +183,7 @@ function exactPackageSpecifier(specifier: string): string | undefined { } /** Narrow an unknown parsed JSON value to the `dsh.client` declaration, throwing on malformed fields. */ -function parseDshClient(pkgName: string, value: unknown): DshClientDeclaration | undefined { +function parseDshClient(pkgName: string, value: unknown): DshClientManifest | undefined { if (value === undefined) return undefined if (typeof value !== 'object' || value === null) { throw new Error(`client-modules: ${pkgName} has a non-object dsh.client declaration`) diff --git a/packages/client/modules/tsconfig.json b/packages/client/modules/tsconfig.json index 6af3e24c7e..4004ef29e3 100644 --- a/packages/client/modules/tsconfig.json +++ b/packages/client/modules/tsconfig.json @@ -11,6 +11,7 @@ { "path": "../../../vendor/cordis" }, { "path": "../../../vendor/loader" }, { "path": "../../host/webserver" }, + { "path": "../../util/package-manifest" }, { "path": "../../runtime-diagnostics/invariants" } ] } diff --git a/packages/experimental/webworker-packer/README.i18n.yaml b/packages/experimental/webworker-packer/README.i18n.yaml index 389916f81b..597b602ea3 100644 --- a/packages/experimental/webworker-packer/README.i18n.yaml +++ b/packages/experimental/webworker-packer/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/experimental/webworker-packer/README.md -README.md: 701f4a41db78fff6c6af532d1e4f8aa43d585577 -README.zh.md: 30682e314c36dbc08bcd895fb7a2277a38f7ea52 +README.md: 598a175637a6111001b07b0186c0f1a465d54a9c +README.zh.md: 8f05e39d34bd33613065cf86fd9c6e51ff90d88e diff --git a/packages/experimental/webworker-packer/README.md b/packages/experimental/webworker-packer/README.md index 701f4a41db..598a175637 100644 --- a/packages/experimental/webworker-packer/README.md +++ b/packages/experimental/webworker-packer/README.md @@ -23,6 +23,8 @@ The VFS image packer: turns one composed profile into the gzip-compressed base t ## Use this package +The [`DshConfigTreeDeclaration`](../../util/package-manifest/README.md) type describes each `dsh.configTrees` entry; this packer validates it and resolves its source directory. + The pack is a three-layer standard stack: 1. **Roster** — the composed profile's plugin rows (standard YAML parse under Include's dialect, `!!js` intact), plus the rows of every config tree the CLI declares in its `package.json` `dsh.configTrees` (agent presets), materialized as a Node-style dependency closure. External peer edges never bind the worker; workspace peers stay on the chain. diff --git a/packages/experimental/webworker-packer/README.zh.md b/packages/experimental/webworker-packer/README.zh.md index 30682e314c..8f05e39d34 100644 --- a/packages/experimental/webworker-packer/README.zh.md +++ b/packages/experimental/webworker-packer/README.zh.md @@ -23,6 +23,8 @@ VFS 镜像打包器:把一份合成 profile 变成浏览器 worker 挂载为 ## 使用本包 +[`DshConfigTreeDeclaration`](../../util/package-manifest/README.zh.md) 描述每个 `dsh.configTrees` 条目;本打包器负责校验并解析其源目录。 + 打包是三层标准栈: 1. **Roster**——合成 profile 的插件行(标准 YAML 解析、Include 方言、`!!js` 原样保留),加上 CLI 在 `package.json` `dsh.configTrees` 里声明的每棵配置树(agent presets)的行,按 Node 式依赖闭包物化。外部包的 peer 边不追,workspace peer 保留在链上。 diff --git a/packages/experimental/webworker-packer/package.json b/packages/experimental/webworker-packer/package.json index 3c8250ff6c..5fc68aa9d1 100644 --- a/packages/experimental/webworker-packer/package.json +++ b/packages/experimental/webworker-packer/package.json @@ -40,7 +40,8 @@ "devDependencies": { "@deepseek-ai/cordis": "workspace:^", "@types/js-yaml": "^4.0.9", - "@types/picomatch": "^3.0.2" + "@types/picomatch": "^3.0.2", + "@deepseek-ai/dsh-package-manifest": "workspace:^" }, "peerDependencies": { "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/experimental/webworker-packer/src/repository.ts b/packages/experimental/webworker-packer/src/repository.ts index cdfda6e547..535eb6f78a 100644 --- a/packages/experimental/webworker-packer/src/repository.ts +++ b/packages/experimental/webworker-packer/src/repository.ts @@ -12,6 +12,7 @@ import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync } from 'node import { tmpdir } from 'node:os' import { join, relative } from 'node:path' import { DSH_HOME_ENV } from '@deepseek-ai/dsh-home-paths' +import type { DshConfigTreeDeclaration } from '@deepseek-ai/dsh-package-manifest' import type { ConfigTree, ImageTree, PackResult } from './pack.ts' /** @@ -96,13 +97,6 @@ export function composeProfile(repoRoot: string, profile: string): string { } } -/** One `dsh.configTrees` declaration entry, validated field by field. */ -interface ConfigTreeDeclaration { - mount: string - path: string - scanRoster?: boolean -} - /** * Config trees the CLI package declares for deployment images * (`dsh.configTrees` in its package.json): `path` is relative to the CLI @@ -125,7 +119,7 @@ export function configTrees(repoRoot: string): ConfigTree[] { } const mounts = new Set() return declared.map((entry, index) => { - const tree = entry as Partial | null + const tree = entry as Partial | null const at = `${CLI_PACKAGE} dsh.configTrees[${String(index)}]` if (tree === null || typeof tree !== 'object' || typeof tree.mount !== 'string' || tree.mount === '' diff --git a/packages/experimental/webworker-packer/tsconfig.json b/packages/experimental/webworker-packer/tsconfig.json index 152b9ad8c2..2357a1ec84 100644 --- a/packages/experimental/webworker-packer/tsconfig.json +++ b/packages/experimental/webworker-packer/tsconfig.json @@ -19,6 +19,9 @@ }, { "path": "../../util/home-paths" + }, + { + "path": "../../util/package-manifest" } ] } diff --git a/packages/util/README.i18n.yaml b/packages/util/README.i18n.yaml index 35defcb799..8453741048 100644 --- a/packages/util/README.i18n.yaml +++ b/packages/util/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/util/README.md -README.md: ab201cfbc33a51e1713804532f9c6d0a5003c19c -README.zh.md: 751370c822a05da1b050d96bdcf9afbee1d0ea39 +README.md: 2e46d9d4573b31afa14d7f1380af106c391d19d6 +README.zh.md: c7d8b63dc3ee7e748e8a07a3d65315ff81d5476f diff --git a/packages/util/README.md b/packages/util/README.md index ab201cfbc3..2e46d9d457 100644 --- a/packages/util/README.md +++ b/packages/util/README.md @@ -27,6 +27,7 @@ Each package provides one primitive; open a package page for how to use it. | Package | Role | |---|---| | [`brand/`](brand/README.md) | Nominal string types and their stateless constructor | +| [`package-manifest/`](package-manifest/README.md) | Shared TypeScript declarations for package manifests | | [`crypto/`](crypto/README.md) | Mints RFC 9562 v4 UUIDs from the cross-runtime `crypto.getRandomValues` primitive | | [`deque/`](deque/README.md) | Provides amortized constant-time queue operations with bounded vacant storage | | [`values/`](values/README.md) | Validates, snapshots, compares, and freezes lossless JSON-compatible values | diff --git a/packages/util/README.zh.md b/packages/util/README.zh.md index 751370c822..c7d8b63dc3 100644 --- a/packages/util/README.zh.md +++ b/packages/util/README.zh.md @@ -27,6 +27,7 @@ kind: "package-group" | 包 | 职责 | |---|---| | [`brand/`](brand/README.zh.md) | 提供名义字符串类型及其无状态构造函数 | +| [`package-manifest/`](package-manifest/README.zh.md) | Package manifest 的共享 TypeScript 声明 | | [`crypto/`](crypto/README.zh.md) | 基于跨运行时 `crypto.getRandomValues` 原语生成 RFC 9562 v4 UUID | | [`deque/`](deque/README.zh.md) | 提供摊销常数时间的队列操作和有界空闲存储 | | [`values/`](values/README.zh.md) | 校验、创建快照、比较和冻结无损 JSON 兼容值 | diff --git a/packages/util/package-manifest/README.i18n.yaml b/packages/util/package-manifest/README.i18n.yaml new file mode 100644 index 0000000000..50561fa3f3 --- /dev/null +++ b/packages/util/package-manifest/README.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# side as of the last confirmed-consistent state. Both languages carry equal authority; +# after editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write packages/util/package-manifest/README.md +README.md: 565f175979eddfd27412f64fdb65dd34e013771e +README.zh.md: a0e5895c42c40bb4bd1f2ab3d8d103c8ca51997c diff --git a/packages/util/package-manifest/README.md b/packages/util/package-manifest/README.md new file mode 100644 index 0000000000..565f175979 --- /dev/null +++ b/packages/util/package-manifest/README.md @@ -0,0 +1,85 @@ +--- +description: "Shared TypeScript declarations for package.json.dsh metadata, usable by boot, client, build, and external packages." +kind: "package-library" +--- + +# @deepseek-ai/dsh-package-manifest + +English | [中文](README.zh.md) + +## Summary + +Use `DshManifest` to type a package's Harness metadata, or a member type such as `DshClientManifest` for one declaration. Boot, client, build, and external packages import the same types; each reader owns JSON validation and default resolution. + +## Table of Contents + +- [Use this package](#use-this-package) +- [Understand the implementation](#understand-the-implementation) +- [Further Exploration](#further-exploration) +- [Model Experience](#model-experience) +- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work) +- [Dev Note](#dev-note) + +----- + + +## Use this package + +Import from the package root. Use a development dependency when only checking your own source; use a production dependency if your published declarations reference these types. + +```ts +import type { DshClientManifest, DshManifest } from '@deepseek-ai/dsh-package-manifest' + +const client: DshClientManifest = { platform: 'web' } +const dsh: DshManifest = { + bundle: { patch: './cordis.patch.yml' }, + client, +} +``` + +`DshManifest` describes `bundle`, `profile`, `client`, `configTrees`, `sessionFormatMigration`, and `moduleFallback`, not the surrounding npm manifest. `moduleFallback` is launcher-generated metadata and is not an author configuration entry. TypeScript checks this object and erases `import type` during compilation; JSON files cannot import types, and this example does not write a `package.json`. See [`src/types.ts`](src/types.ts) for the declarations. + +----- + + +## Understand the implementation + +
+Implementation internals — click to expand + +The package root only re-exports declarations from [`src/types.ts`](src/types.ts). It has no runtime state or independently observable relationships, so it publishes no runtime invariant companion. + +
+ +----- + + +## Further Exploration + +- [Profile launcher](../../boot/app-boot/README.md#profiles) — manifest loading and composition. +- [Declaration ownership](../../../.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.md) — scope and dependency rationale. + + +## Model Experience + +None, as this package only exports types. + +#### KV Cache effect + +Type declarations add no model input, so provider cache reuse is unaffected. + +## Known Limitations and Deferred Work + + + +- **Static typing only.** These declarations do not validate JSON, check file existence, or supply defaults. `configTrees` serves the experimental image packer, and `sessionFormatMigration` is discovered only for workspace migration packages; declaring them does not register external plugin behavior. + + +### Dev Note + +
+Working context for maintainers — click to expand + +None. + +
diff --git a/packages/util/package-manifest/README.zh.md b/packages/util/package-manifest/README.zh.md new file mode 100644 index 0000000000..a0e5895c42 --- /dev/null +++ b/packages/util/package-manifest/README.zh.md @@ -0,0 +1,85 @@ +--- +description: "供启动器、客户端、构建工具和外部包共同使用的 package.json.dsh 元数据 TypeScript 声明。" +kind: "package-library" +--- + +# @deepseek-ai/dsh-package-manifest + +[English](README.md) | 中文 + +## 概述 + +使用 `DshManifest` 为包的 Harness 元数据添加类型,也可用 `DshClientManifest` 等成员类型描述单项声明。启动器、客户端、构建工具和外部包导入同一组类型;各读取方负责 JSON 校验和默认值解析。 + +## 目录 + +- [使用本包](#use-this-package) +- [理解实现](#understand-the-implementation) +- [进一步探索](#further-exploration) +- [模型体验](#model-experience) +- [已知限制与后续工作](#known-limitations-and-deferred-work) +- [开发备注](#dev-note) + +----- + + +## 使用本包 + +从包根导入类型。仅检查自己的源码时使用开发依赖;若发布的声明文件引用这些类型,则使用生产依赖。 + +```ts +import type { DshClientManifest, DshManifest } from '@deepseek-ai/dsh-package-manifest' + +const client: DshClientManifest = { platform: 'web' } +const dsh: DshManifest = { + bundle: { patch: './cordis.patch.yml' }, + client, +} +``` + +`DshManifest` 描述 `bundle`、`profile`、`client`、`configTrees`、`sessionFormatMigration` 和 `moduleFallback`,不包含外层 npm manifest。`moduleFallback` 是启动器生成的元数据,不是作者配置项。TypeScript 检查该对象,并在编译时删除 `import type`;JSON 文件不能导入类型,此示例也不会写入 `package.json`。声明见 [`src/types.ts`](src/types.ts)。 + +----- + + +## 理解实现 + +
+实现细节——点击展开 + +包根仅重新导出 [`src/types.ts`](src/types.ts) 中的声明。本包没有运行时状态或可独立观察的关系,因此不发布运行时不变量伴随模块。 + +
+ +----- + + +## 进一步探索 + +- [Profile 启动器](../../boot/app-boot/README.zh.md#profiles)——manifest 加载与组合。 +- [声明归属](../../../.agents/notes/implemented/architecture/2026-09-05-package-manifest-types.zh.md)——范围与依赖依据。 + + +## 模型体验 + +无,因为本包仅导出类型。 + +#### KV Cache 影响 + +类型声明不增加模型输入,因此不影响提供方的缓存复用。 + +## 已知限制与后续工作 + + + +- **仅提供静态类型。** 这些声明不校验 JSON、不检查文件存在性,也不提供默认值。`configTrees` 服务于实验性镜像打包器,`sessionFormatMigration` 仅从工作区迁移包中发现;声明它们不会注册外部插件行为。 + + +### 开发备注 + +
+维护者的工作上下文——点击展开 + +无。 + +
diff --git a/packages/util/package-manifest/package.json b/packages/util/package-manifest/package.json new file mode 100644 index 0000000000..c8beff5baa --- /dev/null +++ b/packages/util/package-manifest/package.json @@ -0,0 +1,35 @@ +{ + "name": "@deepseek-ai/dsh-package-manifest", + "description": "Shared type declarations for package.json.dsh configuration fields", + "version": "0.1.3-alpha.1", + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/package-manifest" + }, + "type": "module", + "main": "lib/index.js", + "types": "lib/types/index.d.ts", + "exports": { + ".": { + "types": "./lib/types/index.d.ts", + "default": "./lib/index.js" + }, + "./src/*": "./src/*", + "./package.json": "./package.json" + }, + "files": [ + "lib/index.js", + "lib/types/**/*.d.ts" + ], + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "workspace:^" + }, + "devDependencies": { + "@deepseek-ai/cordis": "workspace:^" + } +} diff --git a/packages/util/package-manifest/src/index.ts b/packages/util/package-manifest/src/index.ts new file mode 100644 index 0000000000..2ea0cfd07f --- /dev/null +++ b/packages/util/package-manifest/src/index.ts @@ -0,0 +1,15 @@ +/** + * Public package manifest types, with no runtime exports. + * @module @deepseek-ai/dsh-package-manifest + */ + +export type { + DshBundleManifest, + DshClientManifest, + DshConfigTreeDeclaration, + DshManifest, + DshModuleFallbackManifest, + DshProfileManifest, + DshSessionFormatMigrationManifest, + ProfilePatchReload, +} from './types.ts' diff --git a/packages/util/package-manifest/src/types.ts b/packages/util/package-manifest/src/types.ts new file mode 100644 index 0000000000..2c98c63dc3 --- /dev/null +++ b/packages/util/package-manifest/src/types.ts @@ -0,0 +1,99 @@ +/** + * Shared declarations for `package.json.dsh`. + * Each reader owns JSON validation and resolved defaults. + * @module @deepseek-ai/dsh-package-manifest/types + */ + +/** The `dsh` property of an npm manifest; a package may declare several roles. */ +export interface DshManifest { + /** Bundle metadata consumed by the profile launcher. */ + bundle?: DshBundleManifest + /** Profile metadata consumed by the profile launcher. */ + profile?: DshProfileManifest + /** Client module loading and build metadata. */ + client?: DshClientManifest + /** Config directories consumed by the experimental deployment-image packer. */ + configTrees?: DshConfigTreeDeclaration[] + /** Adjacent Session migration metadata consumed by the workspace catalog generator. */ + sessionFormatMigration?: DshSessionFormatMigrationManifest + /** + * Launcher-generated module proxy metadata, not an author configuration entry. + * @internal + */ + moduleFallback?: DshModuleFallbackManifest +} + +/** The configuration layer exported by a bundle package. */ +export interface DshBundleManifest { + /** Patch file path relative to the declaring package root. */ + patch: string +} + +/** The bundle composition declared by a profile directory. */ +export interface DshProfileManifest { + /** Ordered bundle layer list, using installed package names. */ + bundles?: string[] + /** User patch lifecycle; omitted means `live` for custom profiles. */ + patchReload?: ProfilePatchReload +} + +/** Whether user patch files reload while a profile remains active or apply only at startup. */ +export type ProfilePatchReload = 'live' | 'startup' + +/** Client module declaration read by client-modules and the client build. */ +export interface DshClientManifest { + /** Client platform identifier; the Web consumer selects `web`. */ + platform: string + /** Informational package-name dependencies, not Cordis service injection. */ + inject?: string[] + /** Boot phase-one registration barrier; absent means the shared application batch. */ + immediately?: boolean + /** + * Exact module-table requests beyond the implicit client baseline, including + * subpaths such as `/client`; absent means baseline externals only. + * Type-only imports are erased and create no module request. + */ + external?: string[] +} + +/** One config directory read from the CLI package by the experimental image packer. */ +export interface DshConfigTreeDeclaration { + /** Non-empty destination path in the image; mount values must be unique. */ + mount: string + /** Non-empty source directory path relative to the declaring package root. */ + path: string + /** Include the directory's YAML plugin rows in the package roster; absent means false. */ + scanRoster?: boolean +} + +/** + * Adjacent Session migration metadata declared on disk. The catalog generator + * discovers only packages/session/session-format-vN-to-vN+1, not external plugins. + */ +export interface DshSessionFormatMigrationManifest { + /** Non-negative safe integer source version; negative zero is rejected. */ + from: number + /** Non-negative safe integer target version, exactly from + 1. */ + to: number + /** Non-empty package export path, such as `.` or `./migration`. */ + export: string + /** Non-empty named export of the migration implementation. */ + migration: string + /** Non-empty named export of the source version codec. */ + sourceCodec: string + /** Non-empty named export of the target version codec. */ + targetCodec: string + /** Non-empty named export of the target header validator. */ + targetHeaderValidator: string + /** Non-empty named export of the target version restorer. */ + targetRestorer: string +} + +/** + * Metadata generated and read by the launcher's module fallback proxies. + * @internal + */ +export interface DshModuleFallbackManifest { + /** Package export subpaths mapped to resolved target file URLs. */ + targets: Record +} diff --git a/packages/util/package-manifest/tsconfig.json b/packages/util/package-manifest/tsconfig.json new file mode 100644 index 0000000000..250fdad007 --- /dev/null +++ b/packages/util/package-manifest/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib/types", + "types": [] + }, + "include": [ + "src" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a286e8db0a..da2ef9a8ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,9 @@ importers: .: devDependencies: + '@deepseek-ai/dsh-package-manifest': + specifier: workspace:^ + version: link:packages/util/package-manifest '@deepseek-ai/dsh-tool-session-query': specifier: workspace:^ version: link:packages/session-query/tool-session-query @@ -973,6 +976,9 @@ importers: '@deepseek-ai/dsh-atomic-write': specifier: workspace:^ version: link:../../util/atomic-write + '@deepseek-ai/dsh-package-manifest': + specifier: workspace:^ + version: link:../../util/package-manifest js-yaml: specifier: ^4.2.0 version: 4.2.0 @@ -1863,6 +1869,9 @@ importers: '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-package-manifest': + specifier: workspace:^ + version: link:../../util/package-manifest packages/client/store: dependencies: @@ -4907,6 +4916,9 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis + '@deepseek-ai/dsh-package-manifest': + specifier: workspace:^ + version: link:../../util/package-manifest '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 @@ -9413,6 +9425,12 @@ importers: specifier: workspace:^ version: link:../../../vendor/cordis + packages/util/package-manifest: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + packages/util/time: devDependencies: '@deepseek-ai/cordis': diff --git a/scripts/doc-standard.spec.ts b/scripts/doc-standard.spec.ts index 91bea8fbe5..02773f6001 100644 --- a/scripts/doc-standard.spec.ts +++ b/scripts/doc-standard.spec.ts @@ -85,6 +85,7 @@ const PACKAGE_LIBRARIES: Readonly> = { 'packages/util/launch-environment': 'Zero-dependency environment resolver.', 'packages/util/native-command': 'Host-side subprocess runner utility.', 'packages/util/output-retention': 'Zero-dependency retention utility.', + 'packages/util/package-manifest': 'Shared package manifest declarations with type-only exports.', 'packages/util/time': 'Zero-dependency time-zone canonicalization utility.', 'packages/util/timeout': 'Zero-dependency timeout utility.', 'packages/util/values': 'Stateless lossless-JSON and immutable-value helpers.', diff --git a/scripts/gen-session-format-catalog.ts b/scripts/gen-session-format-catalog.ts index 9ffb6d6653..2886a5e224 100644 --- a/scripts/gen-session-format-catalog.ts +++ b/scripts/gen-session-format-catalog.ts @@ -3,21 +3,15 @@ import { globSync, readFileSync, writeFileSync } from 'node:fs' import { resolve } from 'node:path' import { pathToFileURL } from 'node:url' +import type { DshSessionFormatMigrationManifest } from '@deepseek-ai/dsh-package-manifest' const root = resolve(import.meta.dirname, '..') const OUT = 'packages/session/session-format-catalog/src/generated.ts' -/** One adjacent migration declaration read from a workspace manifest. */ -export interface SessionFormatMigrationManifest { +/** Validated adjacent migration metadata with its resolved package import path. */ +export interface SessionFormatMigrationManifest extends Readonly> { readonly packageName: string readonly importPath: string - readonly from: number - readonly to: number - readonly migration: string - readonly sourceCodec: string - readonly targetCodec: string - readonly targetHeaderValidator: string - readonly targetRestorer: string } interface RawManifest { @@ -78,7 +72,7 @@ export function collectSessionFormatMigrations( if (metadata === undefined) { throw new Error(`gen-session-format-catalog: ${rel} lacks dsh.sessionFormatMigration`) } - const allowed = new Set([ + const allowed: ReadonlySet = new Set([ 'from', 'to', 'export', 'migration', 'sourceCodec', 'targetCodec', 'targetHeaderValidator', 'targetRestorer', ]) diff --git a/scripts/verify-package-readme-model-experience.ts b/scripts/verify-package-readme-model-experience.ts index f514ba8c7e..33010ed079 100644 --- a/scripts/verify-package-readme-model-experience.ts +++ b/scripts/verify-package-readme-model-experience.ts @@ -57,6 +57,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly> = { 'packages/client/ui-agent-preset': { kind: 'indirect', reason: 'Browser-side settings row; the preset it selects owns every model-facing effect.' }, 'packages/util/crypto': { kind: 'indirect', reason: 'Pure identifier minting; the ids consumers mint with it never enter prompts as semantic content.' }, 'packages/util/deque': { kind: 'none', reason: 'In-process collection primitive; registers nothing model-facing.' }, + 'packages/util/package-manifest': { kind: 'none', reason: 'Type declarations only; registers nothing model-facing.' }, 'packages/util/time': { kind: 'indirect', reason: 'Pure zone validation; the consumer that records a canonical zone owns the model-visible line derived from it.' }, 'packages/core/agent-default-model': { kind: 'indirect', reason: 'The service supplies a ModelSelection; request assembly and adapters own the model-visible request.' }, 'packages/llm/deepseek-llm-api-extensions': { kind: 'indirect', reason: 'The registry contributes model-hidden provider fields; dsh-llm-deepseek owns their wire placement.' }, diff --git a/tsconfig.base.json b/tsconfig.base.json index e0749acbb4..fad1323d4f 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -308,6 +308,7 @@ "@deepseek-ai/dsh-message-feedback": ["./packages/feedback/message-feedback/src"], "@deepseek-ai/dsh-native-command": ["./packages/util/native-command/src"], "@deepseek-ai/dsh-output-retention": ["./packages/util/output-retention/src"], + "@deepseek-ai/dsh-package-manifest": ["./packages/util/package-manifest/src"], "@deepseek-ai/dsh-permission-presets": ["./packages/interaction/permission-presets/src"], "@deepseek-ai/dsh-permission-presets/invariant": ["./packages/interaction/permission-presets/src/invariant.ts"], "@deepseek-ai/dsh-persona": ["./packages/preset/persona/src"], diff --git a/tsconfig.host.json b/tsconfig.host.json index 85ae2dac00..fe4eebeb52 100644 --- a/tsconfig.host.json +++ b/tsconfig.host.json @@ -131,6 +131,7 @@ { "path": "./vendor/hmr" }, { "path": "./vendor/logger-console" }, { "path": "./packages/util/brand" }, + { "path": "./packages/util/package-manifest" }, { "path": "./packages/util/http-proxy" }, { "path": "./packages/util/launch-environment" }, { "path": "./packages/util/native-command" },