Ver código fonte

docs(boot): describe declared ids, author-facing manifest keys, and refresh the catalogs

The publish guide still told bundle authors that mounted row ids carry the
package prefix and that `!!js` gates should compare names, a scheme this
stack withdrew: ids stay as declared, and a shared id or a repeated one
leaves the bundle out with the reason. It now says so, and names
`dsh.title` and `dsh.plugins` with a pointer to the manifest package that
declares every key. The cordis catalog follows app-boot's changed exports.
Yichen Jiang 1 mês atrás
pai
commit
613adbb231

+ 2 - 2
docs/subsystems/core.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/subsystems/core.md
-core.md: ac515c0fdeef3606d0d1a9d3fe1cbbdf1998b325
-core.zh.md: 34fc938dd5a50224dc76afd3dbe137517342e319
+core.md: 9a8633a4e62b87f98629df95a96aa5b1910f50e9
+core.zh.md: f204532ed2dcb862587c23892af37c50684b0483

+ 7 - 4
docs/subsystems/core.md

@@ -854,8 +854,9 @@ originOf(rowId: string): RowOrigin | undefined
 
 /**
  * Row ids the user patch layers disable with a literal `disabled: true`.
- * A `!!js` gate in a user file is a condition, not a user decision, and is
- * left to the composition.
+ * A `!!js` gate in a user file stays an expression node when read from
+ * disk, so it is a condition, not a user decision, and is left to the
+ * composition.
  * @returns the ids, re-read from disk on every call.
  */
 userDisabledRowIds(): Set<string>
@@ -865,8 +866,10 @@ userDisabledRowIds(): Set<string>
  * as they stand now. The root Include re-applies the stack transactionally:
  * a row whose options changed is updated in place, a row that appeared is
  * created, a row that vanished is disposed, and a failure rolls the whole
- * update back with the previous tree still running. The rows the stack left
- * out replace the failure registry's conflict records once the update holds.
+ * update back with the previous tree still running. The candidate profile,
+ * its ownership, and its conflicts become the committed composition only
+ * once the update holds; until then, and after a rejection, `current`,
+ * `layers`, `originOf`, and `conflicts` keep describing the running tree.
  * @param options - `reloadBundles` re-reads the profile manifest first, so a
  * bundle enabled or installed since boot joins the stack.
  * @throws when the root include is not mounted, or the Loader rejected the update.

+ 7 - 4
docs/subsystems/core.zh.md

@@ -864,8 +864,9 @@ originOf(rowId: string): RowOrigin | undefined
 
 /**
  * Row ids the user patch layers disable with a literal `disabled: true`.
- * A `!!js` gate in a user file is a condition, not a user decision, and is
- * left to the composition.
+ * A `!!js` gate in a user file stays an expression node when read from
+ * disk, so it is a condition, not a user decision, and is left to the
+ * composition.
  * @returns the ids, re-read from disk on every call.
  */
 userDisabledRowIds(): Set<string>
@@ -875,8 +876,10 @@ userDisabledRowIds(): Set<string>
  * as they stand now. The root Include re-applies the stack transactionally:
  * a row whose options changed is updated in place, a row that appeared is
  * created, a row that vanished is disposed, and a failure rolls the whole
- * update back with the previous tree still running. The rows the stack left
- * out replace the failure registry's conflict records once the update holds.
+ * update back with the previous tree still running. The candidate profile,
+ * its ownership, and its conflicts become the committed composition only
+ * once the update holds; until then, and after a rejection, `current`,
+ * `layers`, `originOf`, and `conflicts` keep describing the running tree.
  * @param options - `reloadBundles` re-reads the profile manifest first, so a
  * bundle enabled or installed since boot joins the stack.
  * @throws when the root include is not mounted, or the Loader rejected the update.

+ 2 - 2
docs/user/develop/basic/publish.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/user/develop/basic/publish.md
-publish.md: 816b36ac99695c95332ae99439c1ccfc3c4a8732
-publish.zh.md: c3918913d6cb09b212eae35902a375539bb047cb
+publish.md: 6ebac3de6d364bb4bc05d364197d11ada85a0c8c
+publish.zh.md: 012878d3be0eb15704423107a4cbd1b79790966e

+ 3 - 1
docs/user/develop/basic/publish.md

@@ -43,6 +43,8 @@ Create `hello-plugin/package.json`:
 }
 ```
 
+Two more `dsh` keys describe the package to people: `dsh.title` names it in the plugin list, and `dsh.plugins` lists modules a user can add to a composition one at a time, beside the layer the bundle mounts as a whole — each entry names the module (`"name": "dsh-hello-plugin/extra"`) with an optional `title` and default `config`. Every `dsh` key is declared in [`@deepseek-ai/dsh-package-manifest`](../../../../packages/util/package-manifest/README.md).
+
 Create `hello-plugin/index.js` with the plugin entry point:
 
 ```js
@@ -109,7 +111,7 @@ dsh --profile demo
 
 `dsh plugin --profile demo remove dsh-hello-plugin` removes both the dependency and the layer.
 
-An installed bundle mounts as an external layer: the dump shows its rows inside one group named `bundle/dsh-hello-plugin`, and each row id carries the package prefix, so the row above is `dsh-hello-plugin/hello` in the mounted tree — a user patch that targets it names that id. A row of yours that fails to start is isolated and reported in the plugin list instead of stopping `dsh`; if your bundle provides a service the built-in rows inject, declare `dsh.bundle.stage: boot` so it mounts like a built-in one and fails loud. Prefixing does not rewrite string literals, so a `!!js` disabled expression that compares `e.options.id` to your own id should compare `e.options.name` instead.
+An installed bundle mounts as an external layer: the dump shows its rows inside one group named `bundle/dsh-hello-plugin`, and each row keeps the id your patch declares, so the row above is `hello` in the mounted tree and a user patch that targets it names that id. Row ids are shared across every layer: if another layer already declares one of yours, or your patch declares one twice, the whole bundle is left out and the reason is printed at boot and shown in the plugin list. A row of yours that fails to start is isolated and reported in the plugin list instead of stopping `dsh`; if your bundle provides a service the built-in rows inject, declare `dsh.bundle.stage: boot` so it mounts like a built-in one and fails loud.
 
 ## The loading order
 

+ 3 - 1
docs/user/develop/basic/publish.zh.md

@@ -43,6 +43,8 @@ hello-plugin/
 }
 ```
 
+另有两个 `dsh` 键面向使用者描述这个包:`dsh.title` 是它在插件列表里的名字,`dsh.plugins` 列出使用者可以逐个加进组合的模块,与组合包整体挂载的层并列——每一项写模块名(`"name": "dsh-hello-plugin/extra"`),可选 `title` 与默认 `config`。所有 `dsh` 键都声明在 [`@deepseek-ai/dsh-package-manifest`](../../../../packages/util/package-manifest/README.zh.md) 里。
+
 创建 `hello-plugin/index.js`,写入插件入口:
 
 ```js
@@ -109,7 +111,7 @@ dsh --profile demo
 
 `dsh plugin --profile demo remove dsh-hello-plugin` 会同时移除依赖和对应的层。
 
-已安装的组合包作为外部层挂载:dump 会把它的行显示在一个名为 `bundle/dsh-hello-plugin` 的组里,每个行 id 带上包名前缀,因此上面那一行在挂载后的树里是 `dsh-hello-plugin/hello`——针对它的用户 patch 要写这个 id。你的某一行启动失败时会被隔离并在插件列表里报告,而不是让 `dsh` 停下;如果你的组合包提供内置行所注入的服务,请声明 `dsh.bundle.stage: boot`,让它像内置行一样挂载并明确失败。前缀不会改写字符串字面量,因此用 `e.options.id` 与自己 id 比较的 `!!js` disabled 表达式应改为比较 `e.options.name`。
+已安装的组合包作为外部层挂载:dump 会把它的行显示在一个名为 `bundle/dsh-hello-plugin` 的组里,每一行保持你的 patch 所声明的 id,因此上面那一行在挂载后的树里仍是 `hello`,针对它的用户 patch 就写这个 id。行 id 在所有层之间共用:如果别的层已经声明了你的某个 id,或者你的 patch 把一个 id 声明了两次,整个组合包会被排除,原因在启动时打印并显示在插件列表里。你的某一行启动失败时会被隔离并在插件列表里报告,而不是让 `dsh` 停下;如果你的组合包提供内置行所注入的服务,请声明 `dsh.bundle.stage: boot`,让它像内置行一样挂载并明确失败。
 
 ## 加载顺序
 

+ 2 - 2
packages/extensions/tool-cordis/src/api-catalog.ts

@@ -1399,13 +1399,13 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
       },
       {
         signature: 'userDisabledRowIds(): Set<string>',
-        description: 'Row ids the user patch layers disable with a literal `disabled: true`. A `!!js` gate in a user file is a condition, not a user decision, and is left to the composition.',
+        description: 'Row ids the user patch layers disable with a literal `disabled: true`. A `!!js` gate in a user file stays an expression node when read from disk, so it is a condition, not a user decision, and is left to the composition.',
         parameters: [],
         returns: 'the ids, re-read from disk on every call.',
       },
       {
         signature: 'async recompose(options: { reloadBundles?: boolean } = {}): Promise<void>',
-        description: 'Recompose the host tree from the profile\'s layers and the user patch files as they stand now. The root Include re-applies the stack transactionally: a row whose options changed is updated in place, a row that appeared is created, a row that vanished is disposed, and a failure rolls the whole update back with the previous tree still running. The rows the stack left out replace the failure registry\'s conflict records once the update holds.',
+        description: 'Recompose the host tree from the profile\'s layers and the user patch files as they stand now. The root Include re-applies the stack transactionally: a row whose options changed is updated in place, a row that appeared is created, a row that vanished is disposed, and a failure rolls the whole update back with the previous tree still running. The candidate profile, its ownership, and its conflicts become the committed composition only once the update holds; until then, and after a rejection, `current`, `layers`, `originOf`, and `conflicts` keep describing the running tree.',
         parameters: [{ name: 'options', description: '`reloadBundles` re-reads the profile manifest first, so a bundle enabled or installed since boot joins the stack.' }],
         throws: ['when the root include is not mounted, or the Loader rejected the update.'],
       },