dsh-primer 0.4.5 → 0.4.6

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.
Files changed (80) hide show
  1. package/README.en.md +6 -6
  2. package/README.es.md +6 -6
  3. package/README.hi.md +6 -6
  4. package/README.md +7 -7
  5. package/README.pt.md +6 -6
  6. package/SKILL.md +11 -9
  7. package/data/facts.json +35 -15
  8. package/data/seams/index.json +1526 -98
  9. package/data/standards.json +17 -11
  10. package/dist/dsh-plugin-dev.js +22 -37
  11. package/guide/links.md +2 -2
  12. package/guide/migration-0.2.md +105 -14
  13. package/guide/plugin-dev-guide.md +6 -6
  14. package/guide/quick-reference.es.md +4 -4
  15. package/guide/quick-reference.hi.md +4 -4
  16. package/guide/quick-reference.md +4 -4
  17. package/guide/quick-reference.pt.md +4 -4
  18. package/guide/quick-reference.zh-CN.md +4 -4
  19. package/guide/standards.md +1 -1
  20. package/guide/standards.zh-CN.md +1 -1
  21. package/guide/unfixed-issues.md +2 -2
  22. package/guide/version-matrix.md +65 -42
  23. package/package.json +13 -7
  24. package/references/official-docs/CLAUDE.md +1 -1
  25. package/references/official-docs/README.md +9 -4
  26. package/references/official-docs/SNAPSHOT.md +7 -5
  27. package/references/official-docs/docs/capability-seams.i18n.yaml +2 -2
  28. package/references/official-docs/docs/capability-seams.md +4 -0
  29. package/references/official-docs/docs/capability-seams.zh.md +4 -0
  30. package/references/official-docs/docs/config-catalog.md +26 -28
  31. package/references/official-docs/docs/config-catalog.zh.md +26 -28
  32. package/references/official-docs/docs/defensive-patterns/package-surface.i18n.yaml +2 -2
  33. package/references/official-docs/docs/defensive-patterns/package-surface.md +0 -1
  34. package/references/official-docs/docs/defensive-patterns/package-surface.zh.md +0 -1
  35. package/references/official-docs/docs/event-producer-consumer.md +1 -1
  36. package/references/official-docs/docs/event-producer-consumer.zh.md +1 -1
  37. package/references/official-docs/docs/module-graph.md +12 -17
  38. package/references/official-docs/docs/module-graph.zh.md +12 -17
  39. package/references/official-docs/docs/subsystems/computer-use.i18n.yaml +2 -2
  40. package/references/official-docs/docs/subsystems/computer-use.md +1 -1
  41. package/references/official-docs/docs/subsystems/computer-use.zh.md +1 -1
  42. package/references/official-docs/docs/subsystems/persistence.md +19 -0
  43. package/references/official-docs/docs/subsystems/persistence.zh.md +19 -0
  44. package/references/official-docs/docs/subsystems/ptc-runtime.i18n.yaml +4 -4
  45. package/references/official-docs/docs/subsystems/ptc-runtime.md +8 -48
  46. package/references/official-docs/docs/subsystems/ptc-runtime.zh.md +8 -48
  47. package/references/official-docs/docs/tool-catalog.i18n.yaml +2 -2
  48. package/references/official-docs/docs/tool-catalog.md +1 -1
  49. package/references/official-docs/docs/tool-catalog.zh.md +1 -1
  50. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.i18n.yaml +4 -4
  51. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.md +7 -7
  52. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.zh.md +7 -7
  53. package/references/official-plugin-dev-skill.md +16 -12
  54. package/references/sources.md +2 -2
  55. package/scripts/check-docs-drift.mjs +121 -0
  56. package/scripts/check-docs-drift.ps1 +4 -1
  57. package/scripts/check-facts.mjs +81 -3
  58. package/scripts/sync-official-docs.ps1 +16 -5
  59. package/templates/js/README-es.md +1 -1
  60. package/templates/js/README-hi.md +1 -1
  61. package/templates/js/README-pt.md +1 -1
  62. package/templates/js/README-zh.md +1 -1
  63. package/templates/js/README.md +1 -1
  64. package/templates/ts/README-es.md +1 -1
  65. package/templates/ts/README-hi.md +1 -1
  66. package/templates/ts/README-pt.md +1 -1
  67. package/templates/ts/README-zh.md +1 -1
  68. package/templates/ts/README.md +1 -1
  69. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.i18n.yaml +0 -16
  70. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.md +0 -26
  71. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.zh.md +0 -26
  72. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.i18n.yaml +0 -16
  73. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.md +0 -25
  74. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.zh.md +0 -25
  75. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.i18n.yaml +0 -16
  76. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.md +0 -48
  77. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.zh.md +0 -48
  78. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.i18n.yaml +0 -16
  79. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.md +0 -45
  80. package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.zh.md +0 -45
@@ -19,15 +19,13 @@ interface PtcRunRequest {
19
19
  /**
20
20
  * The program source, in the runtime's {@link ../index.ts | language}. It
21
21
  * follows the provider's programFormat: an async function body supports
22
- * top-level `await` and `return`; REPL (`repl`, `scoped-repl`) and Script programs support top-level
22
+ * top-level `await` and `return`; REPL and Script programs support top-level
23
23
  * declarations, `await`, and a final expression, but not top-level `return`.
24
24
  * The Script provider lowers top-level await; its executionInstructions and
25
25
  * documentation define retained-binding semantics. The completion value
26
26
  * becomes {@link PtcRunResult.value}.
27
27
  */
28
28
  program: string
29
- /** Discard the completion without JSON validation when true; omission preserves the completion value. */
30
- discardCompletion?: boolean
31
29
  /**
32
30
  * Object-identity owner for optional in-memory state. Omission requests a fresh
33
31
  * environment. Consumers must await runtime.release(owner) when the owner ends.
@@ -95,12 +93,11 @@ interface PtcRunResult {
95
93
  */
96
94
  value?: PtcJsonValue
97
95
  /**
98
- * Captured text fragments retain their emitted line breaks. Concatenate adjacent text without separators.
99
- * Each source channel preserves emission order; interleaving
96
+ * Captured text. Each source channel preserves emission order; interleaving
100
97
  * across independent channels is backend-dependent. Bounded only as part of
101
98
  * the outer result.
102
99
  */
103
- output: PtcOutput[]
100
+ logs: string[]
104
101
  /** Present iff the run failed; see {@link PtcRunFailure} for the taxonomy. */
105
102
  error?: PtcRunFailure
106
103
  }
@@ -108,10 +105,10 @@ interface PtcRunResult {
108
105
 
109
106
  ```ts type-equiv
110
107
  /** Source evaluation form, independent of retained program state. */
111
- type PtcProgramFormat = 'function-body' | 'repl' | 'script' | 'scoped-repl'
108
+ type PtcProgramFormat = 'function-body' | 'repl' | 'script'
112
109
  ```
113
110
 
114
- `programFormat` distinguishes async function bodies, REPL statements, scoped REPL statements, and scripts. REPL, scoped REPL, and Script programs accept top-level `await`, declarations, and a final expression; top-level `return` is not supported. Retained REPL calls share one scope, while each scoped REPL call starts with copies of the top-level bindings that earlier calls left, so it can declare those names again without changing earlier code. The Node Script provider lowers top-level await and awaits the completion value; its [declaration limitations](../../packages/ptc-runtime/ptc-runtime-node/README.md#known-limitations-and-deferred-work) apply to transformed programs. `retainsState` reports memory retention independently of source syntax. `stateOwner` is an in-process object identity for optional retained memory; distinct objects remain isolated. Consumers await `release(owner)` when that owner ends; cleanup failures reject that call. Omitted owners are one-shot, and stateless providers ignore ownership. The [persistent Node provider](../../packages/ptc-runtime/ptc-runtime-node/README.md#persistent-repl) defines reset and recovery behavior; no retained object enters the durable Session format.
111
+ `programFormat` distinguishes async function bodies, REPL statements, and scripts. REPL and Script programs accept top-level `await`, declarations, and a final expression; top-level `return` is not supported. The Node Script provider lowers top-level await and awaits the completion value; its [declaration limitations](../../packages/ptc-runtime/ptc-runtime-node/README.md#known-limitations-and-deferred-work) apply to transformed programs. `retainsState` reports memory retention independently of source syntax. `stateOwner` is an in-process object identity for optional retained memory; distinct objects remain isolated. Consumers await `release(owner)` when that owner ends; cleanup failures reject that call. Omitted owners are one-shot, and stateless providers ignore ownership. The [persistent Node provider](../../packages/ptc-runtime/ptc-runtime-node/README.md#persistent-repl) defines reset and recovery behavior; no retained object enters the durable Session format.
115
112
 
116
113
  ## Bindings: host functions as program globals
117
114
 
@@ -153,7 +150,7 @@ interface PtcBindingNamespace {
153
150
  * words, so the same namespace list works against every backend regardless
154
151
  * of `language` — a JS-only spelling like `$tools` is rejected by design,
155
152
  * not just by the Python backend. Names that satisfy the identifier rule but
156
- * name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `inspect`, `console`, `Image`,
153
+ * name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `console`,
157
154
  * `__dsh_main__`) are also refused everywhere; see its declaration for the
158
155
  * exact set and why each entry is reserved.
159
156
  */
@@ -174,7 +171,7 @@ type PtcJsonValue = null | boolean | number | string | PtcJsonValue[] | { [key:
174
171
  /**
175
172
  * One host-side function exposed to the program as an async callable. The
176
173
  * runtime bridges calls to it (possibly across a serialization boundary), so
177
- * `args` must be lossless JSON; resolutions also support host-issued PtcImage values. A runtime rejects a
174
+ * `args` and the resolution value MUST be lossless JSON. A runtime rejects a
178
175
  * lossy or non-cloneable value with a descriptive error rather than corrupting
179
176
  * the run. No seam-level byte cap applies to a binding resolution. A rejection
180
177
  * of this function surfaces inside the program as a rejection of the
@@ -185,29 +182,7 @@ type PtcBindingFunction = (args: unknown) => Promise<PtcJsonValue>
185
182
 
186
183
  ## Captured output and the failure taxonomy
187
184
 
188
- `output` contains text and image entries in emission order: `{ type: 'text', text }` or `{ type: 'image', attachment }`. Text entries retain emitted newline characters; concatenate adjacent text without separators. Each source channel preserves emission order; interleaving across independent channels is backend-dependent. Host bindings return `PtcImage` descriptors containing the attachment reference and a readable execution-world `path`; the program receives an `Image` with that path and the stored pixel dimensions. The Node provider caps serialized text, image descriptors, and completion or diagnostic payloads together; overflow is an explicit failure.
189
-
190
- ```ts public-api
191
- /** A stored image readable from the program's execution environment. */
192
- declare class PtcImage {
193
- readonly [key: string]: PtcJsonValue;
194
- /** Absolute attachment file path readable in the execution world. */
195
- readonly path: string;
196
- /** Stored image selected when the program inspects this value. */
197
- readonly attachment: Readonly<ImageAttachmentRef>;
198
- /**
199
- * Describe one immutable image file in the execution world.
200
- * @param path - Absolute path to the stored image.
201
- * @param attachment - Reference to the immutable stored image.
202
- */
203
- constructor(path: string, attachment: ImageAttachmentRef);
204
- }
205
- ```
206
-
207
- ```ts type-equiv
208
- /** Raw text fragments and inspected images in emission order; concatenate adjacent text without separators. */
209
- type PtcOutput = { type: 'text'; text: string } | { type: 'image'; attachment: ImageAttachmentRef }
210
- ```
185
+ Logs are plain strings. Each source channel preserves emission order, while interleaving across independent channels is backend-dependent because channel metadata is not part of the seam. The runtime captures the program's console and stream output, and consumers render only the text. Implementations cap the serialized outer log-array plus completion-value or failure-message payload; fixed result-envelope syntax and consumer presentation whitespace are not part of that variable-payload ledger. Overflow is an explicit failure rather than in-band value substitution.
211
186
 
212
187
  Failure kinds are **orthogonal outcomes reported independently** (per [defensive-patterns](../defensive-patterns/general.md)): a budget expiry is not an exception, an abort is not a timeout, and a substrate death (e.g. OOM) is neither:
213
188
 
@@ -262,21 +237,6 @@ Registers one `ctx.ptcRuntime` implementation. Program, budget, abort, and subst
262
237
  */
263
238
  release(owner: object): Promise<void>
264
239
 
265
- /**
266
- * Register source evaluated once when each execution environment is created.
267
- * Registration must precede the first run admission; only one initializer may
268
- * be registered. Current bindings are installed before initialization. Its
269
- * completion is discarded; logs, timeout, cancellation and output bounds share
270
- * the first run. Initialization failure discards the environment without
271
- * executing the user program or rolling back external effects.
272
- * @param program - Initialization source in the provider's language and format.
273
- * @returns An idempotent async disposer that stops admission, cancels and drains
274
- * admitted runs, and releases environments. Failed cleanup blocks execution
275
- * until the disposer succeeds on retry. The caller owns this disposer.
276
- * @throws When unsupported, registered twice, registered after admission, or invalid.
277
- */
278
- registerEnvironmentInitializer(program: string): () => Promise<void>
279
-
280
240
  /**
281
241
  * Resolve supported options and provider defaults before execution.
282
242
  * @param request - Program, bindings, cancellation and optional execution choices.
@@ -19,15 +19,13 @@ interface PtcRunRequest {
19
19
  /**
20
20
  * The program source, in the runtime's {@link ../index.ts | language}. It
21
21
  * follows the provider's programFormat: an async function body supports
22
- * top-level `await` and `return`; REPL (`repl`, `scoped-repl`) and Script programs support top-level
22
+ * top-level `await` and `return`; REPL and Script programs support top-level
23
23
  * declarations, `await`, and a final expression, but not top-level `return`.
24
24
  * The Script provider lowers top-level await; its executionInstructions and
25
25
  * documentation define retained-binding semantics. The completion value
26
26
  * becomes {@link PtcRunResult.value}.
27
27
  */
28
28
  program: string
29
- /** Discard the completion without JSON validation when true; omission preserves the completion value. */
30
- discardCompletion?: boolean
31
29
  /**
32
30
  * Object-identity owner for optional in-memory state. Omission requests a fresh
33
31
  * environment. Consumers must await runtime.release(owner) when the owner ends.
@@ -95,12 +93,11 @@ interface PtcRunResult {
95
93
  */
96
94
  value?: PtcJsonValue
97
95
  /**
98
- * Captured text fragments retain their emitted line breaks. Concatenate adjacent text without separators.
99
- * Each source channel preserves emission order; interleaving
96
+ * Captured text. Each source channel preserves emission order; interleaving
100
97
  * across independent channels is backend-dependent. Bounded only as part of
101
98
  * the outer result.
102
99
  */
103
- output: PtcOutput[]
100
+ logs: string[]
104
101
  /** Present iff the run failed; see {@link PtcRunFailure} for the taxonomy. */
105
102
  error?: PtcRunFailure
106
103
  }
@@ -108,10 +105,10 @@ interface PtcRunResult {
108
105
 
109
106
  ```ts type-equiv
110
107
  /** Source evaluation form, independent of retained program state. */
111
- type PtcProgramFormat = 'function-body' | 'repl' | 'script' | 'scoped-repl'
108
+ type PtcProgramFormat = 'function-body' | 'repl' | 'script'
112
109
  ```
113
110
 
114
- `programFormat` 区分异步函数体、REPL 语句、scoped REPL 语句与脚本。REPL、scoped REPL 与 Script 程序接受顶层 `await`、声明和末尾表达式,不支持顶层 `return`。保留状态的 REPL 各次调用共用一个作用域;scoped REPL 每次调用开始时拿到之前调用留下的顶层绑定的拷贝,因此可以再次声明这些名字,而不改变之前的代码。Node Script 提供方转换顶层 await 并等待完成值;其[声明限制](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#known-limitations-and-deferred-work)适用于转换后的程序。`retainsState` 独立于源码语法报告是否保留内存。`stateOwner` 是标识可选保留内存的进程内对象身份;不同对象相互隔离。消费者在所有者结束时等待 `release(owner)`;清理失败时该调用拒绝。省略所有者时仅执行一次,无状态提供方忽略所有权。[持久 Node 提供方](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#persistent-repl)定义重置和恢复行为;保留对象不会进入持久 Session 格式。
111
+ `programFormat` 区分异步函数体、REPL 语句与脚本。REPL 与 Script 程序接受顶层 `await`、声明和末尾表达式,不支持顶层 `return`。Node Script 提供方转换顶层 await 并等待完成值;其[声明限制](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#known-limitations-and-deferred-work)适用于转换后的程序。`retainsState` 独立于源码语法报告是否保留内存。`stateOwner` 是标识可选保留内存的进程内对象身份;不同对象相互隔离。消费者在所有者结束时等待 `release(owner)`;清理失败时该调用拒绝。省略所有者时仅执行一次,无状态提供方忽略所有权。[持久 Node 提供方](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#persistent-repl)定义重置和恢复行为;保留对象不会进入持久 Session 格式。
115
112
 
116
113
  ## 绑定:宿主函数作为程序全局变量
117
114
 
@@ -153,7 +150,7 @@ interface PtcBindingNamespace {
153
150
  * words, so the same namespace list works against every backend regardless
154
151
  * of `language` — a JS-only spelling like `$tools` is rejected by design,
155
152
  * not just by the Python backend. Names that satisfy the identifier rule but
156
- * name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `inspect`, `console`, `Image`,
153
+ * name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `console`,
157
154
  * `__dsh_main__`) are also refused everywhere; see its declaration for the
158
155
  * exact set and why each entry is reserved.
159
156
  */
@@ -174,7 +171,7 @@ type PtcJsonValue = null | boolean | number | string | PtcJsonValue[] | { [key:
174
171
  /**
175
172
  * One host-side function exposed to the program as an async callable. The
176
173
  * runtime bridges calls to it (possibly across a serialization boundary), so
177
- * `args` must be lossless JSON; resolutions also support host-issued PtcImage values. A runtime rejects a
174
+ * `args` and the resolution value MUST be lossless JSON. A runtime rejects a
178
175
  * lossy or non-cloneable value with a descriptive error rather than corrupting
179
176
  * the run. No seam-level byte cap applies to a binding resolution. A rejection
180
177
  * of this function surfaces inside the program as a rejection of the
@@ -185,29 +182,7 @@ type PtcBindingFunction = (args: unknown) => Promise<PtcJsonValue>
185
182
 
186
183
  ## 捕获的输出与失败分类体系
187
184
 
188
- `output` 按发出顺序保存文本和图片条目:文本使用 `{ type: 'text', text }`,图片使用 `{ type: 'image', attachment }`。文本条目保留实际输出的换行,相邻文本直接拼接,不额外插入分隔符。每个来源通道都保留发出顺序;独立通道之间的交错顺序由后端决定。宿主绑定返回 `PtcImage` 描述符,包含附件引用和可在执行环境读取的 `path`;程序收到带有该路径和存储像素尺寸的 `Image`。Node 提供方对序列化文本、图片描述符、完成值或诊断一起计量;超限会显式失败。
189
-
190
- ```ts public-api
191
- /** A stored image readable from the program's execution environment. */
192
- declare class PtcImage {
193
- readonly [key: string]: PtcJsonValue;
194
- /** Absolute attachment file path readable in the execution world. */
195
- readonly path: string;
196
- /** Stored image selected when the program inspects this value. */
197
- readonly attachment: Readonly<ImageAttachmentRef>;
198
- /**
199
- * Describe one immutable image file in the execution world.
200
- * @param path - Absolute path to the stored image.
201
- * @param attachment - Reference to the immutable stored image.
202
- */
203
- constructor(path: string, attachment: ImageAttachmentRef);
204
- }
205
- ```
206
-
207
- ```ts type-equiv
208
- /** Raw text fragments and inspected images in emission order; concatenate adjacent text without separators. */
209
- type PtcOutput = { type: 'text'; text: string } | { type: 'image'; attachment: ImageAttachmentRef }
210
- ```
185
+ 日志是纯字符串。每个来源通道保留自身的发出顺序;由于通道元数据不属于 seam,相互独立的通道如何交错由后端决定。运行时捕获程序的 console 与流输出,Consumer 只渲染文本。实现会对序列化后的外层日志数组,以及完成值或失败消息的组合载荷设置上限;固定的结果封装语法与 Consumer 展示空白不计入这份可变载荷计量。超限会显式失败,而不会在值中插入替代内容。
211
186
 
212
187
  失败类型是**正交的结果,独立报告**(见 [defensive-patterns](../defensive-patterns/general.zh.md)):预算耗尽不是异常,中止不是超时,基底崩溃(如 OOM)也不是二者中的任何一个:
213
188
 
@@ -262,21 +237,6 @@ Registers one `ctx.ptcRuntime` implementation. Program, budget, abort, and subst
262
237
  */
263
238
  release(owner: object): Promise<void>
264
239
 
265
- /**
266
- * Register source evaluated once when each execution environment is created.
267
- * Registration must precede the first run admission; only one initializer may
268
- * be registered. Current bindings are installed before initialization. Its
269
- * completion is discarded; logs, timeout, cancellation and output bounds share
270
- * the first run. Initialization failure discards the environment without
271
- * executing the user program or rolling back external effects.
272
- * @param program - Initialization source in the provider's language and format.
273
- * @returns An idempotent async disposer that stops admission, cancels and drains
274
- * admitted runs, and releases environments. Failed cleanup blocks execution
275
- * until the disposer succeeds on retry. The caller owns this disposer.
276
- * @throws When unsupported, registered twice, registered after admission, or invalid.
277
- */
278
- registerEnvironmentInitializer(program: string): () => Promise<void>
279
-
280
240
  /**
281
241
  * Resolve supported options and provider defaults before execution.
282
242
  * @param request - Program, bindings, cancellation and optional execution choices.
@@ -72,8 +72,8 @@
72
72
  en: 8c8643ef46fd075f
73
73
  zh: 8c8643ef46fd075f
74
74
  /tool-schema-catalog/deepseek-ai-dsh-tool-executor-ptc/run-code:
75
- en: 2c7a3166dfd9751c
76
- zh: 1b52ae2d0f33b9a4
75
+ en: 7917e16cbc2c366f
76
+ zh: c39eb0420544f04a
77
77
  /tool-schema-catalog/deepseek-ai-dsh-plan-mode:
78
78
  en: b500b530845e26a9
79
79
  zh: b500b530845e26a9
@@ -623,7 +623,7 @@ ask_user_question keeps the original blocking behavior by default; set `mode: ti
623
623
 
624
624
  ### `run_code`
625
625
 
626
- Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Show selected text and images with inspect(...values). The program is the body of an async TypeScript function; only erasable syntax is accepted, with no enum or namespaces. Type annotations are advisory. Top-level await and return are supported. Use inspect(...values) to display output. Do not use console. Each call runs in a fresh Node process. Node APIs are available through await import(...). Relative paths use the supplied working directory; process.env starts empty. Direct filesystem access follows this execution's sandbox policy. Each program starts in the Session's current directory. Running programs keep their initial directory. A sandbox escalation approves this complete program for one execution only. Nested tools retain their own policies and approvals. Request wider access only after evidence of a denial. Earlier effects may already have completed: inspect them before explicitly retrying. Programs are never replayed automatically.
626
+ Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return is program output — curate it. Image-bearing subtool results are attached after the run. The program is the body of an async TypeScript function; only erasable syntax is accepted, with no enum or namespaces. Type annotations are advisory. Top-level await and return are supported. Emit output with console.log(...) or return a lossless JSON value. Only printed values and the returned value become program output. Each call runs in a fresh Node process. Node APIs are available through await import(...). Relative paths use the supplied working directory; process.env starts empty. Direct filesystem access follows this execution's sandbox policy. Each program starts in the Session's current directory. Running programs keep their initial directory. A sandbox escalation approves this complete program for one execution only. Nested tools retain their own policies and approvals. Request wider access only after evidence of a denial. Earlier effects may already have completed: inspect them before explicitly retrying. Programs are never replayed automatically.
627
627
 
628
628
  ```json
629
629
  {
@@ -627,7 +627,7 @@ ask_user_question 默认保持原有阻塞行为;设置 `mode: timed` 后才
627
627
 
628
628
  ### `run_code`
629
629
 
630
- 针对可用工具执行 TypeScript 程序。接受两个必填参数:`code`,异步函数的函数体(仅限可擦除语法,支持顶层 `await` 和 `return`);以及 `description`,简要说明程序做什么。请按系统提示词中的声明,以 `await tools.name(args)` 调用工具。使用 inspect(...values) 展示选定的文本和图片。程序是异步 TypeScript 函数的函数体,只接受可擦除语法,不支持 enum 或 namespace。类型标注只作提示。支持顶层 await 和 return。使用 inspect(...values) 展示输出。不要使用 console。每次调用在新的 Node 进程中运行,可通过 await import(...) 使用 Node API。相对路径以传入的工作目录为准;process.env 初始为空。直接文件系统访问遵循本次执行的沙箱策略。每个程序从 Session 的当前目录启动,运行中保留初始目录。沙箱提权只为本次完整程序执行授权。嵌套工具保留自身策略与审批。只有在获得拒绝证据后才请求更宽访问。先前效果可能已经发生,请在显式重试前检查。程序不会自动重放。
630
+ 针对可用工具执行 TypeScript 程序。接受两个必填参数:`code`,异步函数的函数体(仅限可擦除语法,支持顶层 `await` 和 `return`);以及 `description`,简要说明程序做什么。请按系统提示词中的声明,以 `await tools.name(args)` 调用工具。只有打印或返回的内容构成程序输出,请筛选这些内容。含图片的子工具结果会在运行结束后附加。程序是异步 TypeScript 函数的函数体,只接受可擦除语法,不支持 enum 或 namespace。类型标注只作提示。支持顶层 await 和 return。使用 console.log(...) 或返回无损 JSON 值来输出。只有打印值和返回值成为程序输出。每次调用在新的 Node 进程中运行,可通过 await import(...) 使用 Node API。相对路径以传入的工作目录为准;process.env 初始为空。直接文件系统访问遵循本次执行的沙箱策略。每个程序从 Session 的当前目录启动,运行中保留初始目录。沙箱提权只为本次完整程序执行授权。嵌套工具保留自身策略与审批。只有在获得拒绝证据后才请求更宽访问。先前效果可能已经发生,请在显式重试前检查。程序不会自动重放。
631
631
 
632
632
  ```json
633
633
  {
@@ -9,8 +9,8 @@
9
9
  en: 207c515390c5e529
10
10
  zh: bd4d90881efb011d
11
11
  /native-cua-application-and-window-api/change:
12
- en: 43ace3409e7976b8
13
- zh: da185b705dfe600a
12
+ en: e5d1027faa55adba
13
+ zh: 4b88ad6a70977fb3
14
14
  /native-cua-application-and-window-api/migration:
15
- en: 33bdef11cad75c53
16
- zh: 0d576c6160278b7b
15
+ en: 071b67613c512b84
16
+ zh: 7ee32d8dbcf7a0f2
@@ -9,15 +9,15 @@ English | [中文](guide.zh.md)
9
9
 
10
10
  ## Change
11
11
 
12
- Screenshots and pointer input require explicit windows. App (`appHandle`) and Window (`windowId`) objects share their application handle's latest accessibility snapshot. Window IDs are opaque strings. macOS retains running application PIDs and permission `helper.pid` and `parent.pid`. Windows permission metadata omits PIDs.
12
+ CUA scripts use an explicit window for screenshots and pointer input. App and Window objects share the latest accessibility snapshot for their application handle. Their identifiers are `appHandle` and `windowId` respectively. Application discovery still reports the PID of a running match.
13
13
 
14
- Providers supply startup capabilities and implement `getGuidance(kind)` instead of supplying a `guidance` string. `raw` selects instructions for the raw `cua` tool; `standalone` selects instructions for `cua_run_code`. The native helper reports runtime permissions and session lock state; the Host combines these with startup capabilities in `getCapabilities()`. Human-facing permission responses carry a `darwin` or `windows` platform tag.
14
+ Providers supply startup capabilities alongside their platform guidance. The native helper reports runtime permissions and session lock state. The Host combines both in `getCapabilities()`. Human-facing permission responses carry a `darwin` or `win32` platform tag.
15
15
 
16
16
  ## Migration
17
17
 
18
- 1. Pass a current `app.getWindows()` ID unchanged to `app.getWindow(windowId)`. Rediscover saved numeric IDs. Use `window.getScreenshot()`, `window.click()`, `window.scroll()`, and `window.drag()`. Replace `hover` with `window.mouseMove()`. On macOS, `window.click(id)` sends mouse events at the element center. Switch to `invoke(id)` for the default accessibility action, or `performAction(id, "AXShowMenu")` to request an advertised menu action.
19
- 2. Replace `getAXState()` with `getAccessibilityTree()`. Replace `getAXStateAndScreenshot()` with separate tree and screenshot reads. Application and window selection does not read AX. Before using element IDs, call `getAccessibilityTree()` explicitly. To display the tree in TypeScript PTC, pass its return value to `inspect`. A screenshot does not require a successful AX read. Before coordinate input, including relative coordinates, obtain a successful AX observation covering the window or a screenshot; absolute coordinates require a screenshot. See [macOS AX read limits](../cua-ax-read-limits/guide.md) for changes to traversal defaults and configuration.
18
+ 1. After `cua.getApp(selector)`, select the target from `app.getWindows()` with `app.getWindow(windowId)`. Use `window.getScreenshot()`, `window.click()`, `window.scroll()`, and `window.drag()`. Replace `hover` with `window.mouseMove()`. On macOS, `window.click(id)` sends mouse events at the element center. Switch to `invoke(id)` for the default accessibility action, or `performAction(id, "AXShowMenu")` to request an advertised menu action.
19
+ 2. Replace `getAXState()` with `getAccessibilityTree()`. Replace `getAXStateAndScreenshot()` with separate tree and screenshot reads. Application and window selection does not read AX. Before using element IDs, call `getAccessibilityTree()` explicitly; use `{ emit: false }` to retain the snapshot without displaying it. A screenshot does not require a successful AX read. Before coordinate input, including relative coordinates, obtain a successful AX observation covering the window or a screenshot; absolute coordinates require a screenshot. See [macOS AX read limits](../cua-ax-read-limits/guide.md) for changes to traversal defaults and configuration.
20
20
  3. Pass the opaque string ID from the latest tree wherever you passed a numeric element index. In raw requests use `elementId` with `snapshotId`. Replace `performSecondaryAction` with `listActions(id)` and `performAction(id, exactName, argument?)`, or use `invoke(id)` for the default action. `setValue` accepts the provider’s supported JSON values. On macOS, `performAction(id, 'AXRaise')` performs the advertised raise action. Call `app.activate()` first when the application must become active.
21
- 4. Replace a packed chord such as `pressKey('shift+Tab')` with `pressKey('Tab', ['shift'])`. Check `(await cua.getCapabilities()).methods` before using `sendKeyEvent`. On macOS, call it inside one `run_code` or `cua_run_code` to hold a key across tool calls. Repeat a held non-modifier with another down. Returning, throwing or pausing releases any remaining keys. Replace `NATIVE_ERROR` with `INVALID_ARGUMENT` for unknown macOS keys and correct the key before retrying.
22
- 5. Read `dispatched`, then observe the outcome. `invoke` returns `dispatched: false` when the element has no default action. Remove reads of the old `verified` field and of `pid` on selected objects or window records. Pass a Windows application ID unchanged. For a specific macOS instance, use `getApp(String(row.pid))`. Update permission readers that test for `win32` to use `windows`.
23
- 6. Custom providers replace `CuaBackend.description` with `capabilities` and `guidance` with `getGuidance(kind)`. Supply `permissionParameters`. Set `acceptsPidSelector: true` if `getApp` accepts process IDs. Rebuild custom `helperPath` against the [operation schema](../../../../packages/experimental/cua/src/protocol.ts) and [tagged permission response](../../../../packages/experimental/cua/src/access-types.ts). Restart. Verify both tool forms’ guidance, advertised methods, keyboard scopes and permission controls.
21
+ 4. Replace a packed chord such as `pressKey('shift+Tab')` with `pressKey('Tab', ['shift'])`. Check `(await cua.getCapabilities()).methods` before using `sendKeyEvent`. On macOS, call it inside one `run_code` to hold a key across tool calls. To request one repeat, send another down for a non-modifier key held by that execution. Returning, throwing or pausing releases any remaining keys. If your script handles unknown macOS key names as `NATIVE_ERROR`, handle `INVALID_ARGUMENT` instead. Correct the key name before retrying.
22
+ 5. Read `dispatched` from action results, then observe the application to verify the outcome. `invoke` returns `dispatched: false` when the element has no default action. Remove reads of the old `verified` field and of `pid` on selected objects or window records. Use `listApps()` or running `findApps()` matches when you need a PID.
23
+ 6. For a custom provider, replace `CuaBackend.description` with `capabilities` and pass `guidance` and `permissionParameters` to `installCua`. Rebuild any custom `helperPath` against the [operation schema](../../../../packages/experimental/cua/src/protocol.ts) and [tagged permission response](../../../../packages/experimental/cua/src/access-types.ts). Restart the provider, inspect its advertised methods and keyboard scopes, and open the Computer Use permission page to verify its platform controls.
@@ -9,15 +9,15 @@ description: "迁移 CUA 脚本和自定义原生提供方,使用显式窗口
9
9
 
10
10
  ## 变更
11
11
 
12
- 截图和指针输入要求显式选择窗口。App(`appHandle`)和 Window(`windowId`)对象共享所属应用句柄的最新辅助功能快照。窗口 ID 是不透明字符串,macOS 应用发现保留运行进程的 PID,权限诊断保留 `helper.pid` 和 `parent.pid`。Windows 权限诊断不提供 PID。
12
+ CUA 脚本在指定窗口上截图和操作鼠标。App 和 Window 对象共享同一应用句柄最近读取的辅助功能快照。App 用 `appHandle` 标识,Window 用 `windowId` 标识。查找应用时,运行中的匹配项仍提供 PID。
13
13
 
14
- 提供方声明启动能力,并实现 `getGuidance(kind)`,不再传入 `guidance` 字符串。`raw` 选择原始 `cua` 工具的指引,`standalone` 选择 `cua_run_code` 的指引。原生 helper 返回运行时权限和会话锁定状态,Host 将其与启动能力合并到 `getCapabilities()` 中。供权限页面使用的响应带有 `darwin` 或 `windows` 平台标记。
14
+ 提供方在安装时声明固定的平台能力并提供操作指引。原生 helper 返回实际的权限和会话锁定状态。Host 合并两者,作为 `getCapabilities()` 的结果。供权限页面使用的响应带有 `darwin` 或 `win32` 平台标记。
15
15
 
16
16
  ## 迁移
17
17
 
18
- 1. 从 `app.getWindows()` 返回的列表选定目标,把原始字符串传给 `app.getWindow(windowId)`。曾以数字保存的窗口 ID 需要重新获取。在窗口上调用 `getScreenshot()`、`click()`、`scroll()` 和 `drag()`,将原有的 `hover` 调用改为 `window.mouseMove()`。在 macOS 上,`window.click(id)` 在元素中心发送鼠标事件。需要执行默认辅助功能动作时,改用 `invoke(id)`。需要打开控件菜单且控件声明了 `AXShowMenu` 时,调用 `performAction(id, "AXShowMenu")`。
19
- 2. 将 `getAXState()` 改为 `getAccessibilityTree()`,将 `getAXStateAndScreenshot()` 拆成读取树和截图两次调用。选择应用或窗口不读取 AX。使用元素 ID 前须显式调用 `getAccessibilityTree()`。在 TypeScript PTC 中,将返回值传给 `inspect` 即可展示这棵树。截图不要求 AX 读取成功。所有坐标输入(包括相对坐标)之前都须成功读取覆盖该窗口的 AX 或取得截图;绝对坐标要求截图。[读取上限的迁移说明](../cua-ax-read-limits/guide.zh.md)列出了 macOS 默认值和配置含义的变化。
18
+ 1. 调用 `cua.getApp(selector)` 后,从 `app.getWindows()` 返回的列表选定目标,再调用 `app.getWindow(windowId)`。在窗口上调用 `getScreenshot()`、`click()`、`scroll()` 和 `drag()`,将原有的 `hover` 调用改为 `window.mouseMove()`。在 macOS 上,`window.click(id)` 在元素中心发送鼠标事件。需要执行默认辅助功能动作时,改用 `invoke(id)`。需要打开控件菜单且控件声明了 `AXShowMenu` 时,调用 `performAction(id, "AXShowMenu")`。
19
+ 2. 将 `getAXState()` 改为 `getAccessibilityTree()`,将 `getAXStateAndScreenshot()` 拆成读取树和截图两次调用。选择应用或窗口不读取 AX。使用元素 ID 前须显式调用 `getAccessibilityTree()`;使用 `{ emit: false }` 可保留快照但不显示树。截图不要求 AX 读取成功。所有坐标输入(包括相对坐标)之前都须成功读取覆盖该窗口的 AX 或取得截图;绝对坐标要求截图。[读取上限的迁移说明](../cua-ax-read-limits/guide.zh.md)列出了 macOS 默认值和配置含义的变化。
20
20
  3. 将数字元素索引改为从最新树中取得的字符串 ID。直接发送请求时使用 `elementId` 和 `snapshotId`。原先调用 `performSecondaryAction` 的地方,先用 `listActions(id)` 取得完整动作名,再调用 `performAction(id, exactName, argument?)`。要执行默认动作,可调用 `invoke(id)`。`setValue` 接受提供方支持的 JSON 值。 在 macOS 上,`performAction(id, 'AXRaise')` 只执行元素声明的抬起窗口动作。需要把应用切到前台时先调用 `app.activate()`。
21
- 4. 将 `pressKey('shift+Tab')` 之类的组合键写法改为 `pressKey('Tab', ['shift'])`。调用 `sendKeyEvent` 前检查 `(await cua.getCapabilities()).methods`。在 macOS 上,同一次 `run_code` 或 `cua_run_code` 中可调用此方法跨工具调用保持按键。如果需要一次重复按下,可在这次执行中对已按住的普通键再发一次 `down`。执行返回、异常退出或用户暂停时会释放仍按着的键。如果脚本用 `NATIVE_ERROR` 识别 macOS 上的未知键名,请改为处理 `INVALID_ARGUMENT`,并在重试前修正键名。
22
- 5. 从动作结果读取 `dispatched`,再观察应用确认效果。元素没有默认动作时,`invoke` 返回 `dispatched: false`。移除读取旧字段 `verified` 的代码,以及对已选对象和窗口记录中 `pid` 的读取。Windows 应用 ID 原样传递。需要选择某个 macOS 进程时,使用 `getApp(String(row.pid))`。读取权限状态时,将原先判断 `win32` 的代码改为判断 `windows`。
23
- 6. 自定义提供方将 `CuaBackend.description` 改为 `capabilities`,将 `guidance` 改为 `getGuidance(kind)`,并向 `installCua` 传入 `permissionParameters`。若 `getApp` 接受进程 ID,设置 `acceptsPidSelector: true`。按[操作协议](../../../../packages/experimental/cua/src/protocol.ts)和[带平台标记的权限响应](../../../../packages/experimental/cua/src/access-types.ts)重新构建自定义 `helperPath` 对应的 helper。重启后验证两种工具形态的指引、声明的方法、键盘输入范围及 Computer Use 权限页的平台控件。
21
+ 4. 将 `pressKey('shift+Tab')` 之类的组合键写法改为 `pressKey('Tab', ['shift'])`。调用 `sendKeyEvent` 前检查 `(await cua.getCapabilities()).methods`。在 macOS 上,同一次 `run_code` 中可调用此方法跨工具调用保持按键。如果需要一次重复按下,可在这次执行中对已按住的普通键再发一次 `down`。执行返回、异常退出或用户暂停时会释放仍按着的键。如果脚本用 `NATIVE_ERROR` 识别 macOS 上的未知键名,请改为处理 `INVALID_ARGUMENT`,并在重试前修正键名。
22
+ 5. 从动作结果读取 `dispatched`,再观察应用确认效果。元素没有默认动作时,`invoke` 返回 `dispatched: false`。移除读取旧字段 `verified` 的代码,以及对已选对象和窗口记录中 `pid` 的读取。需要 PID 时,使用 `listApps()` 或 `findApps()` 返回的运行中应用记录。
23
+ 6. 自定义提供方需将 `CuaBackend.description` 改为 `capabilities`,并向 `installCua` 传入 `guidance` 和 `permissionParameters`。如配置了 `helperPath`,请按[操作协议](../../../../packages/experimental/cua/src/protocol.ts)和[带平台标记的权限响应](../../../../packages/experimental/cua/src/access-types.ts)重新构建 helper。重启提供方,检查它声明的方法和键盘输入范围,再打开 Computer Use 权限页确认平台控件。
@@ -2,21 +2,23 @@
2
2
 
3
3
  > **这是什么**:DeepSeek Harness 自带的 preset(`packages/preset/agent-preset/`)里有一整套**官方插件开发技能**,是 0.2 世代最重要的新增资料——它描述的正是"在当前 Harness 里、由 agent 自己写并安装插件"的官方流程。
4
4
  > **本文件性质**:**要点摘录 + 原文定位**(不是逐字全文;逐字全文随官方文档副本一起在 `references/official-docs/` 之外的仓库路径,需 checkout 才能读)。凡写"官方明确"的地方都能在上游文件里逐字查到。
5
- > **基线**:`d743267388641bc76f17c45ce8b4c231aed1d32c`(`dsh-v0.2.1-alpha.2`,2026-10-09)。升级宿主后若与上游冲突,以上游为准。
6
- > **上游路径**(在 checkout 里,如 `D:\deepseek-harness`):`packages/preset/agent-preset/skills/`
5
+ > **基线**:`38a6a5c965aa99ab525161efb7cc5cf1fe62fced`(`dsh-v0.2.2-rc.3`,2026-11-13)。升级宿主后若与上游冲突,以上游为准。
6
+ > **上游路径**(在 checkout 里,如 `D:\deepseek-harness`):`packages/preset/agent-preset/skills/dsh-doc/`
7
7
 
8
- ## 1. 四个技能与各自职责
8
+ ## 1. 一个技能:`dsh-doc`
9
+
10
+ 从 `0.2.2-rc.1` 起,Creator mode 原来的四个技能(`cordis-plugin-development`、`editing-cordis-compositions`、`cordis-composition-reference`、`agent-experience`)被**合并成一个 `dsh-doc` 技能**(官方指南 `docs/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.md`);rc.3 的 preset 技能目录里只有 `dsh-doc/`(43 个文件)。旧的四个名字只作历史,**不要再去 `skills/cordis-plugin-development/` 找路径**。
9
11
 
10
12
  | 技能 | 职责 |
11
13
  |---|---|
12
- | `cordis-plugin-development/SKILL.md` | 主流程:设计/评审/启用/安装/配置/调试插件、bundle、页面、面板、工具、MCP 连接 |
13
- | `cordis-plugin-development/references/{host-plugin,ui-plugin,mcp-bundle,practices,user-actions,verification}.md` | 六份分面参考(见 §3) |
14
- | `cordis-plugin-development/templates/{decoration,mcp}/**` | 可直接复制的 UI 插件模板与 MCP bundle 模板(含 locale 与 icon) |
15
- | `cordis-composition-reference/SKILL.md` | Loader patch 方言 + 可安装插件包清单 |
16
- | `editing-cordis-compositions/SKILL.md` | agent preset 组合的编辑流程 |
17
- | `agent-experience/SKILL.md` | 面向"模型体验"的写作/设计约束 |
14
+ | `dsh-doc/SKILL.md` | 入口:按"运行时 inspection → 已装文档/包源码 → 声明未核实"的顺序查事实;要改宿主/插件只在用户明确要求时动手 |
15
+ | `dsh-doc/references/plugin-development.md` | **主流程**:bundle 的编写/安装/启用/调试;`plugin_manager` `install_bundle`;禁止手写 profile 清单与在 profile 里跑 pnpm |
16
+ | `dsh-doc/references/{locate-docs,host-plugin,plugin-details,configuration,ui-plugin,mcp-bundle,practices,user-actions,verification,artwork,compositions,upgrading,composition-reference,packages,tool-design}.md` | 分面参考(见 §3;`locate-docs` 讲怎么找当前版本的文档与包源码,`upgrading` 讲升级插件/组合) |
17
+ | `dsh-doc/templates/{decoration,mcp}/**` | 可直接复制的 UI 插件模板与 MCP bundle 模板(含多语 locale 与 icon) |
18
+
19
+ > 仓库贡献者向的 `.agents/skills/**`(如 `dsh-doc-writing`、`dsh-pre-push-checks`)不是 preset 技能、不给插件作者用,别和 `dsh-doc` 混谈。
18
20
 
19
- ## 2. 主流程(`cordis-plugin-development/SKILL.md` 的硬性规定)
21
+ ## 2. 主流程(`dsh-doc/SKILL.md` + `dsh-doc/references/plugin-development.md` 的硬性规定)
20
22
 
21
23
  **安装方式(官方唯一推荐)**:在工作区用普通文件写 bundle,然后用 **`plugin_manager` 工具的 `install_bundle`**,`target` 传**绝对包目录**装进当前 profile。改动对该 profile 的**所有会话**生效并跨重启保留。
22
24
 
@@ -46,7 +48,9 @@
46
48
 
47
49
  **启用随包发布但默认关闭的插件**:行 id 与原因写在随包 patch(源码 checkout 的 `packages/bundle/*/cordis.patch.yml`)里。写一个工作区 bundle,用 patch 覆盖该行为 `disabled: false`,并把它依赖的 Host 行一起插入;源码 checkout 的 `apps/cli/config/examples/<feature>/cordis.yml` 会列出这些行。**随 dsh 发布的包从 dsh 安装位置解析,所以这种 bundle 不声明对它们的依赖。**
48
50
 
49
- ## 3. 六份分面参考的要点
51
+ ## 3. 分面参考的要点(都位于 `dsh-doc/references/`)
52
+
53
+ > 下面按旧文件里最常引用的六份(host-plugin / ui-plugin / mcp-bundle / practices / user-actions / verification)展开;rc.3 的 `dsh-doc/references/` 另有 `plugin-development`、`locate-docs`、`plugin-details`、`configuration`、`artwork`、`compositions`、`upgrading`、`composition-reference`、`packages`、`tool-design` 共 17 份参考,按 SKILL.md 的 "Read next" 表取用。
50
54
 
51
55
  ### 3.1 `host-plugin.md` — bundle 与 Host 插件
52
56
 
@@ -121,4 +125,4 @@
121
125
 
122
126
  - 本文件是**索引与摘录**;机制细节(精确签名、事件 `@mode`、Config schema)永远以 **inspection** 与 `references/official-docs/docs/**` 为准。
123
127
  - 官方这份技能覆盖"在会话里让 agent 写并安装插件";本知识库另外覆盖**对外发布**(npm/tarball/git 通道、`prepare` + `allowBuilds`、五语 README、质量门禁)与**版本迁移**([migration-0.2.md](../guide/migration-0.2.md))。
124
- - 上游路径随宿主版本变化(本文件基线 `d743267`);`preset/agent-presets` → `preset/agent-preset` 的改名发生在 `d1e22a7e24`。
128
+ - 上游路径随宿主版本变化(本文件基线 `dsh-v0.2.2-rc.3` / `38a6a5c9`);`preset/agent-presets` → `preset/agent-preset` 的改名发生在 `d1e22a7e24`,`cordis-plugin-development` → `dsh-doc` 的合并发生在 `v0.2.2-rc.1`。
@@ -33,13 +33,13 @@
33
33
 
34
34
  ## C. 本地 checkout 文档副本(references/official-docs/)
35
35
 
36
- - `docs/**`(**717 个 md**,含 356 个 `.zh.md` 双语对;2026-11-13 重同步到 `dsh-v0.2.2-rc.2`)— 教程/架构/子系统/API/cookbook/upgrade-guide/persistence-changes 全量(计数以 `references/official-docs/SNAPSHOT.md` 为准)
36
+ - `docs/**`(**709 个 md**,含 352 个 `.zh.md` 双语对;2026-11-14 按**发布 tag** `dsh-v0.2.2-rc.3`(`38a6a5c965aa99ab525161efb7cc5cf1fe62fced`)重同步,不再取 master HEAD)— 教程/架构/子系统/API/cookbook/upgrade-guide/persistence-changes 全量(计数以 `references/official-docs/SNAPSHOT.md` 为准)
37
37
  - 仓库根文件(**2026-08-14 晚新增**):`AGENTS.md`、`CLAUDE.md`(上游为 symlink→AGENTS.md,副本存其目标文本)、`BENCHMARK.md`、`CONTRIBUTING.md`/`.zh.md`/`.i18n.yaml`、`README.zh.md`/`.i18n.yaml`、`THIRD_PARTY_NOTICES.md`、`LICENSE`
38
38
  - `packages/AGENTS.md` · `packages/README.md` · `vendor/README.md`
39
39
  - `website-docs.ts`(站点投影清单)
40
40
  - 上游英文 `README.md` 不进入本目录(与 KB 索引同名),线上快照在 `downloads/github/harness/README.md`
41
41
  - 同步脚本本次加固:pathspec 全部 `:(top)` 锚定(避免 basename 全局匹配误收仓库深处 symlink);Windows 下无法解出的 symlink 按其 blob 目标文本落地;目的目录只保留范围内条目(曾因一次失败抽取残留污染,已由脚本自动修剪 107 项)。
42
- - **不在站点路由表里的重要文档**(本地有副本、站上找不到):`session-format-status.md`、`upgrade-guide/**`(6 篇,**无 index、无任何入链**)、`persistence-changes/**`、`ui-radius.md`、`web-styling.md`、`module-graph.md`、`dependency-catalog.json`、`persistence-schema.json`——清单见 [guide/links.md](../guide/links.md) §2.1。
42
+ - **不在站点路由表里的重要文档**(本地有副本、站上找不到):`session-format-status.md`、`upgrade-guide/**`(rc.3 tag 内 12 个版本目录、46 条 0.2.2 线指南;**无 index、无任何入链**)、`persistence-changes/**`、`ui-radius.md`、`web-styling.md`、`module-graph.md`、`dependency-catalog.json`、`persistence-schema.json`——清单见 [guide/links.md](../guide/links.md) §2.1。
43
43
  - **官方自带插件开发技能不在 `docs/` 下**:在 `packages/preset/agent-preset/skills/**`(本库要点摘录见 [official-plugin-dev-skill.md](official-plugin-dev-skill.md))。
44
44
 
45
45
  ## D. 社区与生态(downloads/community/ + references/community-ecosystem.md)
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ // Freshness probe for the tag-pinned official-docs mirror (no checkout required).
3
+ //
4
+ // Why this exists, next to `check-docs-drift.ps1`: that script compares the
5
+ // upstream *branch tip* against the pinned commit, which is the right question
6
+ // only while the mirror tracks master. Since 0.4.6 the mirror is pinned to a
7
+ // **release tag** (`references/official-docs/SNAPSHOT.md` -> `Source ref`), so a
8
+ // branch-tip comparison is guaranteed red even with nothing to do: master is
9
+ // always ahead of the tag by construction.
10
+ //
11
+ // The right question for a tag pin is "is there a newer release tag than the one
12
+ // we mirrored?". This script asks it by version-sorting the remote `dsh-v*` tags
13
+ // and comparing the newest one with the pinned ref and commit. It never edits the
14
+ // mirror; drift is only reported.
15
+ //
16
+ // Usage:
17
+ // node scripts/check-docs-drift.mjs [--repo <url>] [--snapshot <path>]
18
+ // [--fail-on-drift] [--json]
19
+ // Exit codes: 0 = FRESH or report produced, 1 = DRIFT (with --fail-on-drift),
20
+ // 2 = probe could not run (snapshot/parse/fetch failure).
21
+ // In CI (when $GITHUB_OUTPUT is set) it appends `drift=yes|no|error`.
22
+
23
+ import { execFileSync } from 'node:child_process'
24
+ import { readFileSync, existsSync, appendFileSync } from 'node:fs'
25
+ import { join } from 'node:path'
26
+
27
+ const root = process.cwd()
28
+ const argv = process.argv.slice(2)
29
+ const flag = (name, fallback) => {
30
+ const i = argv.indexOf(name)
31
+ return i >= 0 ? (argv[i + 1] ?? true) : fallback
32
+ }
33
+ const asJson = argv.includes('--json')
34
+ const failOnDrift = argv.includes('--fail-on-drift')
35
+ const repo = flag('--repo', 'https://github.com/deepseek-ai/deepseek-harness.git')
36
+ const snapshotPath = join(root, flag('--snapshot', 'references/official-docs/SNAPSHOT.md'))
37
+
38
+ const emit = (driftState) => {
39
+ if (process.env.GITHUB_OUTPUT) {
40
+ appendFileSync(process.env.GITHUB_OUTPUT, `drift=${driftState}\n`)
41
+ }
42
+ }
43
+
44
+ const fail2 = (message) => {
45
+ if (asJson) console.log(JSON.stringify({ state: 'error', message }))
46
+ else console.log(`ERROR: ${message}`)
47
+ emit('error')
48
+ process.exit(2)
49
+ }
50
+
51
+ if (!existsSync(snapshotPath)) fail2(`snapshot not found: ${snapshotPath}`)
52
+ const snapshot = readFileSync(snapshotPath, 'utf8')
53
+ const pinnedCommit = /^\|\s*Source commit\s*\|\s*`([0-9a-f]{40})`\s*\|/m.exec(snapshot)?.[1]
54
+ const pinnedRef = /^\|\s*Source ref\s*\|\s*`([^`]+)`\s*\|/m.exec(snapshot)?.[1]
55
+ if (!pinnedCommit) fail2(`cannot parse the pinned "Source commit" from ${snapshotPath}`)
56
+ if (!pinnedRef) fail2(`cannot parse the pinned "Source ref" from ${snapshotPath}`)
57
+
58
+ let result
59
+ if (/^dsh-v/.test(pinnedRef)) {
60
+ // Tag pin: the newest release tag is the freshness authority.
61
+ let newest
62
+ try {
63
+ const out = execFileSync('git', ['ls-remote', '--tags', '--refs', '--sort=-v:refname', repo, 'refs/tags/dsh-v*'], {
64
+ encoding: 'utf8',
65
+ timeout: 60_000,
66
+ })
67
+ newest = out
68
+ .split('\n')
69
+ .map((line) => /^([0-9a-f]{40})\trefs\/tags\/(.+)$/.exec(line))
70
+ .filter(Boolean)
71
+ .map((m) => ({ sha: m[1], tag: m[2] }))[0]
72
+ } catch (error) {
73
+ fail2(`cannot reach upstream ${repo}: ${error.message.split('\n')[0]}`)
74
+ }
75
+ if (!newest) fail2(`no dsh-v* tags found at ${repo}`)
76
+ const fresh = newest.tag === pinnedRef && newest.sha === pinnedCommit
77
+ result = {
78
+ state: fresh ? 'fresh' : 'drift',
79
+ mode: 'tag',
80
+ pinnedRef,
81
+ pinnedCommit,
82
+ upstreamRef: newest.tag,
83
+ upstreamCommit: newest.sha,
84
+ }
85
+ if (!fresh && newest.tag === pinnedRef) {
86
+ result.message = `the pinned tag ${pinnedRef} now points to ${newest.sha}, not the mirrored ${pinnedCommit}`
87
+ }
88
+ } else {
89
+ // Legacy branch pin (e.g. origin/master): compare the branch tip.
90
+ const branch = pinnedRef.replace(/^origin\//, '')
91
+ let tip
92
+ try {
93
+ const out = execFileSync('git', ['ls-remote', repo, `refs/heads/${branch}`], { encoding: 'utf8', timeout: 60_000 })
94
+ tip = /^([0-9a-f]{40})\t/.exec(out)?.[1]
95
+ } catch (error) {
96
+ fail2(`cannot reach upstream ${repo}: ${error.message.split('\n')[0]}`)
97
+ }
98
+ if (!tip) fail2(`cannot resolve ${branch} at ${repo}`)
99
+ const fresh = tip === pinnedCommit
100
+ result = { state: fresh ? 'fresh' : 'drift', mode: 'branch', pinnedRef, pinnedCommit, upstreamRef: branch, upstreamCommit: tip }
101
+ }
102
+
103
+ if (result.state === 'fresh') {
104
+ if (asJson) console.log(JSON.stringify(result))
105
+ else {
106
+ console.log(`pinned (SNAPSHOT.md): ${result.pinnedRef} @ ${result.pinnedCommit}`)
107
+ console.log('FRESH: references/official-docs is pinned to the newest official release tag')
108
+ }
109
+ emit('no')
110
+ process.exit(0)
111
+ }
112
+
113
+ if (asJson) console.log(JSON.stringify(result))
114
+ else {
115
+ console.log(`pinned (SNAPSHOT.md): ${result.pinnedRef} @ ${result.pinnedCommit}`)
116
+ console.log(`upstream: ${result.upstreamRef} @ ${result.upstreamCommit}`)
117
+ console.log(`DRIFT: ${result.message ?? 'a newer official release tag exists than the one mirrored'}`)
118
+ console.log(`Action: run pwsh -File scripts/sync-official-docs.ps1 -Ref ${result.upstreamRef} to refresh the mirror (do not hand-edit it).`)
119
+ }
120
+ emit('yes')
121
+ process.exit(failOnDrift ? 1 : 0)
@@ -1,4 +1,7 @@
1
- # dsh-plugin-guide official-docs freshness probe.
1
+ # dsh-plugin-guide official-docs freshness probe (LEGACY branch-tip probe).
2
+ # NOTE: since 0.4.6 the mirror is pinned to a release tag (`Source ref` in SNAPSHOT.md);
3
+ # comparing the master tip is then always "drift". Use `node scripts/check-docs-drift.mjs`
4
+ # (also what CI runs) for tag pinning; keep this script for a branch-pinned snapshot.
2
5
  # Purpose: detect drift between the KB mirror (references/official-docs) and the
3
6
  # upstream deepseek-harness repository WITHOUT a local checkout. It compares the
4
7
  # upstream branch tip SHA (git ls-remote) against the pinned "Source commit" SHA