Merge remote-tracking branch 'origin/master' into worktree/fix-multi-select-custom-answer

# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
#	packages/ui/tool-ask-user/README.i18n.yaml
#	packages/ui/tool-ask-user/README.zh.md
#	packages/ui/tui/README.i18n.yaml
#	packages/ui/user-interaction/README.i18n.yaml
#	packages/ui/user-interaction/README.zh.md
This commit is contained in:
Yichen Jiang
2026-07-30 00:24:24 +08:00
778 changed files with 24424 additions and 4438 deletions

View File

@@ -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/architecture.md
architecture.md: 2ae982eba49b6dbd2365496915f9917071167813
architecture.zh.md: abaef961504ff64dbcd1e8e8ba9bd002406fa7f4
architecture.md: bb5414d6bb108056bf2ff25366e5afe261e1803a
architecture.zh.md: 6d39a320019a1bf87141be0874a5a20a51fc3fbb

View File

@@ -97,10 +97,10 @@ forever:
'assistant/chunk'
'assistant/message'
schedule tool calls by ctx.tools.executionMode:
exclusive -> one-call barrier
parallel -> rolling pool, <= maxParallelToolCalls in flight; reclassify before start
each start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
each model-order result -> ordered tools/post-execute -> 'tool/result'
exclusive -> barrier
parallel -> rolling pool, <= maxParallelToolCalls; reclassify-at-start; scheduler failure -> stop starts, drain dispatches
start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
model-order result -> ordered tools/post-execute -> 'tool/result'
drain accepted tool context and steering
'step/end'
continue for tools or steering unless a result concluded the turn

View File

@@ -97,10 +97,10 @@ forever:
'assistant/chunk'
'assistant/message'
schedule tool calls by ctx.tools.executionMode:
exclusive -> one-call barrier
parallel -> rolling pool, <= maxParallelToolCalls in flight; reclassify before start
each start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
each model-order result -> ordered tools/post-execute -> 'tool/result'
exclusive -> barrier
parallel -> rolling pool, <= maxParallelToolCalls; reclassify-at-start; scheduler failure -> stop starts, drain dispatches
start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
model-order result -> ordered tools/post-execute -> 'tool/result'
drain accepted tool context and steering
'step/end'
continue for tools or steering unless a result concluded the turn

View File

@@ -1203,7 +1203,7 @@ export interface Config {
}
```
Source: [`packages/session-title/session-title/src/index.ts:75`](../packages/session-title/session-title/src/index.ts)
Source: [`packages/session-title/session-title/src/index.ts:79`](../packages/session-title/session-title/src/index.ts)
## `@deepseek-ai/dsh-session-title-all-messages-llm`
@@ -1241,7 +1241,7 @@ export interface Config {
}
```
Source: [`packages/skill/skill/src/index.ts:113`](../packages/skill/skill/src/index.ts)
Source: [`packages/skill/skill/src/index.ts:170`](../packages/skill/skill/src/index.ts)
## `@deepseek-ai/dsh-skill-local`
@@ -1256,12 +1256,24 @@ export interface Config {
agentsHome?: string
/** Additional skill roots scanned after project roots and before user roots. */
customSkillDirs?: string[]
/** Whether host-local skill roots are watched for catalog changes. */
watch?: boolean
/** Whether Chokidar uses polling instead of native filesystem events. */
watchUsePolling?: boolean
/** Milliseconds a changed skill entry must remain stable before it is observed. */
watchStabilityThresholdMs?: number
/** Milliseconds between Chokidar stability or polling probes. */
watchPollIntervalMs?: number
/** Maximum distinct project roots whose skill directories remain watched. */
watchMaxProjects?: number
/** Whether watched symbolic links follow their target files. */
watchFollowSymlinks?: boolean
/** Bundled skill root; defaults to `$DSH_BUNDLED_SKILL_DIR`, otherwise mounts none. */
bundledSkillDir?: string
}
```
Source: [`packages/skill/skill-local/src/index.ts:41`](../packages/skill/skill-local/src/index.ts)
Source: [`packages/skill/skill-local/src/index.ts:49`](../packages/skill/skill-local/src/index.ts)
## `@deepseek-ai/dsh-spill-local`
@@ -1541,6 +1553,20 @@ export interface Config {
Source: [`packages/context/time-context/src/index.ts:20`](../packages/context/time-context/src/index.ts)
## `@deepseek-ai/dsh-tmux-context`
Requires: `agents`
```ts config-catalog
/** Per-turn tmux-location scheduling. Invalid values fail plugin load. */
export interface Config {
/** Minimum milliseconds between durable injections in one session. Omit or set to 0 to inject on every eligible change. */
refreshIntervalMs?: number
}
```
Source: [`packages/context/tmux-context/src/index.ts:34`](../packages/context/tmux-context/src/index.ts)
## `@deepseek-ai/dsh-token-meter`
```ts config-catalog
@@ -1712,7 +1738,7 @@ Source: [`packages/session-query/tool-session-query/src/index.ts:29`](../package
## `@deepseek-ai/dsh-tool-skill`
Requires: `tools` · `skills`
Requires: `agents` · `tools` · `skills`
```ts config-catalog
/** Model-facing skill catalog configuration. */
@@ -1722,7 +1748,7 @@ export interface Config {
}
```
Source: [`packages/skill/tool-skill/src/index.ts:21`](../packages/skill/tool-skill/src/index.ts)
Source: [`packages/skill/tool-skill/src/index.ts:30`](../packages/skill/tool-skill/src/index.ts)
## `@deepseek-ai/dsh-tool-subagent`

View File

@@ -642,6 +642,25 @@ Types: [Scoped](../core-data-structures/scope.md) · [Session](../core-data-stru
Source: [`packages/core/session/src/index.ts:103`](../../packages/core/session/src/index.ts)
## `skills/*`
### `skills/change` — emit
A skill provider, runtime contribution, or provider-backed catalog may have changed. This is an unfiltered invalidation notification; consumers refetch the catalog for their own lookup options. Listener failures are contained and cannot veto the registry mutation.
```ts cordis-catalog
/**
* A skill provider, runtime contribution, or provider-backed catalog may
* have changed. This is an unfiltered invalidation notification; consumers
* refetch the catalog for their own lookup options. Listener failures are
* contained and cannot veto the registry mutation.
* @mode emit
*/
'skills/change'(): void
```
Source: [`packages/skill/skill/src/index.ts:188`](../../packages/skill/skill/src/index.ts)
## `slash/*`
### `slash/input-begin-command` — bail
@@ -660,7 +679,7 @@ Applies one command claim to the scoped Input. Dispatched with the session's sco
'slash/input-begin-command'(request: BeginCommandRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:230`](../../packages/client/ui-slash/src/types.ts)
Source: [`packages/client/ui-slash/src/types.ts:232`](../../packages/client/ui-slash/src/types.ts)
### `slash/input-consume-token` — bail
@@ -676,7 +695,7 @@ Consumes one command token after business success (popup settle / menu-pick exec
'slash/input-consume-token'(request: ConsumeTokenRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:244`](../../packages/client/ui-slash/src/types.ts)
Source: [`packages/client/ui-slash/src/types.ts:246`](../../packages/client/ui-slash/src/types.ts)
### `slash/input-insert-reference` — bail
@@ -692,7 +711,7 @@ Inserts one reference into the scoped Input (same carrier routing and applied-tr
'slash/input-insert-reference'(request: InsertReferenceRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:237`](../../packages/client/ui-slash/src/types.ts)
Source: [`packages/client/ui-slash/src/types.ts:239`](../../packages/client/ui-slash/src/types.ts)
### `slash/input-insert-text` — bail
@@ -709,7 +728,7 @@ Replaces the trigger token span with literal text — the plain-text reference p
'slash/input-insert-text'(request: InsertTextRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:252`](../../packages/client/ui-slash/src/types.ts)
Source: [`packages/client/ui-slash/src/types.ts:254`](../../packages/client/ui-slash/src/types.ts)
## `subagent/*`

View File

@@ -1604,6 +1604,19 @@ Log-backed title fold plus asynchronous fallback generation.
*/
get(session: Session): SessionTitleSnapshot | undefined
/**
* Accept an explicit user title. Appends a `session/title` event with the
* `user` source, which pins the title: in-flight automatic generation is
* superseded and later user messages schedule none (an explicit
* {@link SessionTitleService.refresh} remains the deliberate unpin).
* @param session - exact live session to rename.
* @param title - raw user input; normalized before acceptance.
* @returns the accepted title snapshot.
* @throws {SessionTitleInvalidError} when the title normalizes to empty.
* @throws {Error} when the session is not live or the service is disposed.
*/
rename(session: Session, title: string): SessionTitleSnapshot
/**
* Explicitly retry the registered provider, or materialize the built-in
* fallback when no provider is registered.
@@ -1624,41 +1637,51 @@ register(provider: SessionTitleProvider): () => Promise<void>
Types: [Session](../core-data-structures/session.md) · [SessionTitleProvider](../core-data-structures/session-title.md) · [SessionTitleSnapshot](../core-data-structures/session-title.md)
Source: [`packages/session-title/session-title/src/index.ts:240`](../../packages/session-title/session-title/src/index.ts)
Source: [`packages/session-title/session-title/src/index.ts:261`](../../packages/session-title/session-title/src/index.ts)
## `ctx.skills` — `SkillService`
Registry of skill providers. It merges provider catalogs with stable first-wins duplicate handling, exposes sorted model-visible summaries, and loads full skill bodies on demand.
Registry of skill providers. It merges provider catalogs with stable first-wins duplicate handling, exposes sorted invocation-neutral summaries, and loads full skill bodies on demand.
```ts cordis-catalog
/**
* Register a borrowed same-process provider synchronously during plugin apply. Duplicate and
* reserved names throw; remote initialization belongs in `list()`. Fiber disposal unregisters
* the provider and invalidates catalog caches.
* @param provider - the provider to register by `provider.name`.
* @param create - synchronous factory receiving this registration's lifecycle and invalidation control.
* @returns the exact Cordis effect disposer that unregisters this provider;
* composite effects may yield it directly to preserve teardown ordering.
*/
registerProvider(provider: SkillProvider): () => void
registerProvider(create: (control: SkillProviderControl) => SkillProvider): () => void
/**
* Register a borrowed readonly runtime skill. Project entries outrank runtime entries, which
* outrank user entries. Same-name runtime entries are first-wins; a duplicate logs a warning and
* receives a no-op disposer so it cannot remove the winner.
* @param skill - the complete skill definition to expose for discovery.
* @param skill - the skill definition input; omitted invocation and provider fields receive defaults.
* @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.
*/
register(skill: SkillRegistration): () => void
/**
* List model-invocable skill summaries for a workspace. Lookup options and
* provider candidates are readonly same-process values borrowed throughout
* discovery.
* List invocation-neutral skill summaries for a workspace. Consumers apply
* model or user invocation policy at their operational boundary. Lookup
* options and provider candidates are readonly same-process values borrowed
* throughout discovery.
* @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.
* @returns sorted summaries, excluding skills disabled for model invocation.
* @returns all sorted winning summaries.
*/
async list(options: SkillLookupOptions = {}): Promise<SkillSummary[]>
/**
* Observe the current invocation-neutral catalog and whether discovery completed within a stable revision.
* Incomplete observations are never cached, allowing consumers to retain last-good state and
* retry on their next request boundary.
* @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.
* @returns sorted summaries plus discovery-completeness state.
*/
async snapshot(options: SkillLookupOptions = {}): Promise<SkillCatalogSnapshot>
/**
* Load and validate the winning candidate, passing its opaque discovery locator back to the
* provider. Cancellation is rechecked after selection, including cache hits, and raced against
@@ -1670,9 +1693,9 @@ async list(options: SkillLookupOptions = {}): Promise<SkillSummary[]>
async get(name: string, options: SkillLookupOptions = {}): Promise<SkillDefinition | undefined>
```
Types: [SkillDefinition](../core-data-structures/skills.md) · [SkillLookupOptions](../core-data-structures/skills.md) · [SkillProvider](../core-data-structures/skills.md) · [SkillRegistration](../core-data-structures/skills.md) · [SkillSummary](../core-data-structures/skills.md)
Types: [SkillCatalogSnapshot](../core-data-structures/skills.md) · [SkillDefinition](../core-data-structures/skills.md) · [SkillLookupOptions](../core-data-structures/skills.md) · [SkillProvider](../core-data-structures/skills.md) · [SkillProviderControl](../core-data-structures/skills.md) · [SkillRegistration](../core-data-structures/skills.md) · [SkillSummary](../core-data-structures/skills.md)
Source: [`packages/skill/skill/src/index.ts:141`](../../packages/skill/skill/src/index.ts)
Source: [`packages/skill/skill/src/index.ts:209`](../../packages/skill/skill/src/index.ts)
## `ctx.spillStore` — `SpillStore` (abstract seam)

View File

@@ -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/core-data-structures/compaction.md
compaction.md: 3ba5edd96c509e064ac7033b175b7ddd3c972452
compaction.zh.md: d082b0d0545802500278e96ca41a273bce275f53
compaction.md: 911b71d00fa4b42e9cdfa67f67d4e9b29e354a4a
compaction.zh.md: 643a116ff2edbbb53d300b4f5ff0ad36d401130b

View File

@@ -13,7 +13,7 @@ Compaction extends [`SessionEventMap`](session.md) with three event types via de
| Event | Payload | Role |
|---|---|---|
| `compact/start` | `{ turn }` | acquires the log-recorded lock |
| `compact/summary` | `{ summary, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens? }` | provenance: the summary blocks, the shadowed surface-boundary pair (`start`/`end` seqs — a position span, not a numeric interval), the shadowed seqs in surface order, the estimated token count, and the summarize call's envelope (`provider`, `model`, plus its generation cap when one applied) — logged so the one-shot request is reconstructable from log + code (the reconstructability Agent Note) |
| `compact/summary` | `{ summary, rawOutput?, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens?, usage? }` | provenance: the safe summary projection, optional complete provider output and usage, the shadowed surface-boundary pair (`start`/`end` seqs — a position span, not a numeric interval), the shadowed seqs in surface order, the estimated token count, and the summarize call's envelope (`provider`, `model`, plus its generation cap when one applied) — logged so the one-shot request is reconstructable from log + code (the reconstructability Agent Note) |
| `compact/end` | `{ turn, error? }` | releases the lock (`error` set when summarization threw) |
The lock brackets the **whole** operation: `compact/start` is appended first, then summarization, the `compact/summary` provenance record, and the `user/message` replacement all land, and only then `compact/end`. Releasing the lock last turns a crash mid-operation into a detectable orphaned lock (a `compact/start` with no matching `compact/end`) rather than a `compact/end` that falsely claims compaction finished.
@@ -22,7 +22,7 @@ These variants are merged inside a `declare module '@deepseek-ai/dsh-session'` b
## `CompactionResult`
What a successful compaction returns to its caller: the bookkeeping-event seqs, raw summary, shadowed range and seqs, and estimated token count.
What a successful compaction returns to its caller: the bookkeeping-event seqs, safe summary projection, shadowed range and seqs, and estimated token count.
```ts type-equiv
/** Result of a successful compaction operation. */

View File

@@ -13,7 +13,7 @@
| 事件 | 载荷 | 作用 |
|---|---|---|
| `compact/start` | `{ turn }` | 获取日志记录的锁 |
| `compact/summary` | `{ summary, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens? }` | provenance摘要块、被遮蔽的 surface 边界对(`start`/`end` seq——位置跨度而非数值区间、按 surface 顺序排列的被遮蔽 seq、估算 token 数,以及摘要调用的 envelope`provider``model`,若有生成上限则还包括该上限)——写入日志后,该一次性请求可由日志 + 代码重建(见可重建性 Agent Note |
| `compact/summary` | `{ summary, rawOutput?, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens?, usage? }` | provenance安全摘要投影、可选的完整 provider 输出与 usage、被遮蔽的 surface 边界对(`start`/`end` seq——位置跨度而非数值区间、按 surface 顺序排列的被遮蔽 seq、估算 token 数,以及摘要调用的 envelope`provider``model`,若有生成上限则还包括该上限)——写入日志后,该一次性请求可由日志 + 代码重建(见可重建性 Agent Note |
| `compact/end` | `{ turn, error? }` | 释放锁(摘要调用抛出异常时设置 `error` |
锁括住**整个**操作:先追加 `compact/start`,然后执行摘要生成、写入 `compact/summary` 来源记录与 `user/message` 替换,最后才追加 `compact/end`。最后释放锁意味着操作中途崩溃会表现为可检测的遗留锁(有 `compact/start` 而无匹配的 `compact/end`),而非一个虚假声称压缩已完成的 `compact/end`
@@ -22,7 +22,7 @@
## `CompactionResult`
成功压缩向调用方返回:记账事件 seq、原始摘要、被遮蔽的范围与 seq以及估算 token 数。
成功压缩向调用方返回:记账事件 seq、安全摘要投影、被遮蔽的范围与 seq以及估算 token 数。
```ts type-equiv
/** Result of a successful compaction operation. */

View File

@@ -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/core-data-structures/session-title.md
session-title.md: 33efc911c0ca1ae94dc4ded74676e5c32a73bdd5
session-title.zh.md: a4b95a726d2bc89a13d14f1daa2f825cd5aa91b1
session-title.md: fff1aa1f6be45d0cfc4d7f6a9527ccb93561618f
session-title.zh.md: 73821b07c6be40d10d0961dd79b7c06bcadb7d0b

View File

@@ -34,6 +34,10 @@ type SessionTitleSource =
readonly provider: SessionTitleProviderId
readonly model?: SessionTitleModelProvenance
}
| {
/** Explicit user rename: pins the title — automatic generation stops scheduling. */
readonly kind: 'user'
}
```
```ts type-equiv
@@ -41,9 +45,9 @@ type SessionTitleSource =
interface SessionTitleEventData {
/** Normalized non-empty title text. */
readonly title: string
/** Exact human `user/message` seqs used to derive this title. */
/** Exact human `user/message` seqs used to derive this title; empty for an explicit user rename. */
readonly messageSeqs: number[]
/** Built-in fallback or registered-provider provenance. */
/** Built-in fallback, registered-provider, or explicit-user provenance. */
readonly source: SessionTitleSource
}
```

View File

@@ -34,6 +34,10 @@ type SessionTitleSource =
readonly provider: SessionTitleProviderId
readonly model?: SessionTitleModelProvenance
}
| {
/** Explicit user rename: pins the title — automatic generation stops scheduling. */
readonly kind: 'user'
}
```
```ts type-equiv
@@ -41,9 +45,9 @@ type SessionTitleSource =
interface SessionTitleEventData {
/** Normalized non-empty title text. */
readonly title: string
/** Exact human `user/message` seqs used to derive this title. */
/** Exact human `user/message` seqs used to derive this title; empty for an explicit user rename. */
readonly messageSeqs: number[]
/** Built-in fallback or registered-provider provenance. */
/** Built-in fallback, registered-provider, or explicit-user provenance. */
readonly source: SessionTitleSource
}
```

View File

@@ -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/core-data-structures/skills.md
skills.md: 2f47881ba5b694ab5affa43add60f340c4d17dbb
skills.zh.md: b5a212f81cc17975cb203738f2636bd5f5695f4f
skills.md: d4b41845bea009444653739abad712e9ce3afb13
skills.zh.md: 8d6793129080487836b2e2471b8659df5a402974

View File

@@ -2,7 +2,7 @@
English | [中文](skills.zh.md)
The [skill capability family](../../packages/skill) is split across three packages: the registry ([dsh-skill](../../packages/skill/skill), `ctx.skills`) merges provider catalogs; the local provider ([dsh-skill-local](../../packages/skill/skill-local)) scans project/custom/user directories; the consumer ([dsh-tool-skill](../../packages/skill/tool-skill)) owns the session-prefix catalog and model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](core.md).
The [skill capability family](../../packages/skill) is split across three packages: the registry ([dsh-skill](../../packages/skill/skill), `ctx.skills`) merges provider catalogs; the local provider ([dsh-skill-local](../../packages/skill/skill-local)) scans and watches project/custom/user directories; the consumer ([dsh-tool-skill](../../packages/skill/tool-skill)) owns the initial and replacement catalogs plus the model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](core.md).
Source: [`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts), [`packages/skill/skill-local/src/index.ts`](../../packages/skill/skill-local/src/index.ts), and [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts).
@@ -10,7 +10,19 @@ Source: [`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/ind
`ctx.skills` combines local, embedded, remote, or other providers. Registration is synchronous; remote initialization and discovery belong in awaited `list()`. Provider objects, options, and candidates are borrowed readonly, while semantic fields are validated.
Duplicate names resolve by rank, provider order, then local order; summaries sort by name. A rejected `list()` is logged and skipped without caching the degraded catalog, while malformed candidates fail fast.
Duplicate names resolve by rank, provider order, then local order; summaries sort by name. A rejected `list()` is logged and omitted from an incomplete observation, while an explicit incomplete observation contributes usable candidates without making the result cacheable; malformed candidates fail fast. Each provider factory receives a registration-scoped control whose `invalidate()` clears completed catalogs only while that exact registration remains active and whose signal aborts on failed registration or disposal. An in-flight discovery retries once when its provider generation changes; a second change returns the latest candidates incomplete and uncached. Provider and runtime mutations emit the unfiltered `skills/change` invalidation event; it carries no diff, so consumers refetch `snapshot()` with their own lookup options.
An array returned by `SkillProvider.list()` is complete-discovery shorthand. `SkillProviderObservation` lets a provider expose candidates that remain directly loadable while reporting that the observation is not authoritative.
```ts type-equiv
/** Provider candidates plus whether the current discovery is authoritative. */
interface SkillProviderObservation {
/** Candidates available from the current provider discovery. */
readonly candidates: readonly SkillCandidate[]
/** Whether discovery completed and these candidates may be cached. */
readonly complete: boolean
}
```
```ts type-equiv
/** Provider interface for one source of skills, such as local directories or a remote registry. */
@@ -23,9 +35,10 @@ interface SkillProvider {
* authentication, and discovery are awaited inside this method. Implementations
* should settle promptly when `options.signal` aborts.
* @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
* @returns provider candidates with precedence ranks and opaque locators.
* @returns provider candidates as a complete-array shorthand, or an explicit
* observation when usable candidates came from incomplete discovery.
*/
readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[]>
readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[] | SkillProviderObservation>
/**
* Load a complete skill body for a previously listed candidate.
* @param candidate - the winning candidate originally returned by this provider.
@@ -36,6 +49,16 @@ interface SkillProvider {
}
```
```ts type-equiv
/** Registration-scoped lifecycle and invalidation capability borrowed by one provider. */
interface SkillProviderControl {
/** Aborts if registration fails or when the exact provider registration is disposed. */
readonly signal: AbortSignal
/** Invalidate completed catalogs and notify consumers only while the exact registration remains active. */
readonly invalidate: () => void
}
```
## Local discovery priority
The shipped local provider scans roots in rank order:
@@ -51,6 +74,8 @@ The shipped local provider scans roots in rank order:
The project root is the nearest ancestor containing `.git`; without one, the current cwd is used. When `ctx.fs` is available, the git-root walk probes `.git` through the filesystem service so remote or sandboxed workspaces do not fall back to the host filesystem boundary. The user DSH root skips its `.system` child. The local provider does not ship built-in system skills; deployments supply built-ins through another provider.
Chokidar watches existing roots for direct bundle/flat-entry additions and removals plus direct skill-entry changes. A missing root is followed one absent path segment at a time from its nearest existing ancestor until Chokidar can attach. Resource files below a bundle are not catalog changes. Model-facing `write` and `edit` observations synchronously invalidate the provider when their target is catalog-relevant, while the host watcher covers IDE, Git, shell, and external-process mutations. Watcher failures make the current observation incomplete without hiding readable candidates from direct loads; project-scoped watchers use a configured bounded LRU.
## Skill identity
Skill names are kebab-case (`^[a-z0-9]+(?:-[a-z0-9]+)*$`). The local provider accepts directory bundles (`<name>/SKILL.md`) and flat Markdown files (`<name>.md`). Nested recursive `**/SKILL.md` discovery is intentionally outside v1.
@@ -62,19 +87,29 @@ type SkillSource = 'project-dsh' | 'project-agents' | 'runtime' | 'user-dsh' | '
## Summaries, candidates, and complete definitions
`SkillSummary` is the registry's model-invocable summary shape. Consumers choose which fields to render; the session catalog uses only `name` and `description`, never the body or absolute file path. `disableModelInvocation` hides a skill from model listings while allowing trusted code to load it by name.
`SkillSummary` is the registry's invocation-neutral summary shape. Consumers choose which entries and fields to render; the model session catalog uses only model-invocable `name` and `description`, never the body or absolute file path. `SkillInvocationPolicy` normalizes the two independent invocation controls into positive booleans, and every resolved summary, candidate, and definition carries it without turning arbitrary frontmatter into the domain model.
```ts type-equiv
/** Model-visible skill metadata returned by `ctx.skills.list()` and rendered into request guidance. */
/** Invocation controls shared by skill discovery consumers. */
interface SkillInvocationPolicy {
/** Whether model-facing catalogs and loaders include this skill. */
readonly modelInvocable: boolean
/** Whether human-facing command catalogs and loaders include this skill. */
readonly userInvocable: boolean
}
```
```ts type-equiv
/** Invocation-neutral skill metadata returned by `ctx.skills.list()`. */
interface SkillSummary {
/** Kebab-case identifier used with the `skill` tool. */
/** Kebab-case identifier used to address the skill. */
readonly name: string
/** Short routing description shown to the model. */
/** Short routing description shown by discovery consumers. */
readonly description: string
/** Optional extra routing guidance shown to the model. */
/** Optional extra routing guidance. */
readonly whenToUse?: string
/** Whether the skill is hidden from model listings while remaining loadable by trusted callers. */
readonly disableModelInvocation?: boolean
/** Resolved model and user invocation controls. */
readonly invocation: SkillInvocationPolicy
/** Discovery source that produced this winning skill. */
readonly source: SkillSource
/** Provider that owns this skill body. */
@@ -84,6 +119,20 @@ interface SkillSummary {
}
```
`ctx.skills.list()` preserves all four policy combinations. `isModelInvocable(skill)` and `isUserInvocable(skill)` read the corresponding required field. A model-only skill sets `{ modelInvocable: true, userInvocable: false }`, a user-only skill sets `{ modelInvocable: false, userInvocable: true }`, and setting both fields to `false` keeps the skill available only through trusted `ctx.skills.get()` callers. The local provider reads the exact kebab-case frontmatter keys `disable-model-invocation` and `user-invocable`, defaults omitted fields to `true`, and projects every parsed skill into this normalized policy.
`SkillCatalogSnapshot` distinguishes authoritative absence from transient provider failure or a catalog that kept changing during discovery. `skills` contains the sorted invocation-neutral summaries collected in that observation; `complete` is true only when every registered provider completed without a concurrent catalog revision. Incomplete snapshots are not cached, allowing each consumer to retain its last-good filtered catalog and retry.
```ts type-equiv
/** One catalog observation plus whether discovery completed within a stable catalog revision. */
interface SkillCatalogSnapshot {
/** Sorted invocation-neutral summaries collected in this observation. */
readonly skills: SkillSummary[]
/** Whether every registered provider completed without a concurrent catalog revision. */
readonly complete: boolean
}
```
`SkillCandidate` is the provider-to-registry shape. `locator` is opaque provider state; the registry only stores it and gives it back to the winning provider's `get()`.
```ts type-equiv
@@ -122,17 +171,24 @@ interface SkillDefinition extends SkillSummary {
}
```
Runtime skills use the same complete shape and participate in the same first-wins collection order. The returned disposer removes the contribution and invalidates discovery caches.
Runtime skill inputs may omit invocation controls and the provider label. The registry resolves both defaults once, then uses the same complete definition shape and first-wins collection order as providers. The returned disposer removes the contribution and invalidates discovery caches.
```ts type-equiv
/** Runtime skill contribution accepted by `ctx.skills.register()`. */
type SkillRegistration = Omit<SkillDefinition, 'provider'> & { readonly provider?: string }
type SkillRegistration = Omit<SkillDefinition, 'invocation' | 'provider'> & {
/** Invocation controls; omission permits both model and user surfaces. */
readonly invocation?: SkillInvocationPolicy
/** Provider label; omission uses the registry-owned runtime provider. */
readonly provider?: string
}
```
## Lookup and configuration
Skill lookup is cwd-sensitive because providers may expose workspace-local skills, and its optional signal cancels provider work for the caller. Providers receive the same readonly options object used for cache identity and loading. Cancellation is checked before and after catalog selection, including cache hits, and races both discovery and full-definition loading. If no git root is found, the local provider treats the supplied cwd itself as the project root.
Full definitions are not cached by the registry. Each `get()` calls the winning provider with the selected candidate, so the local provider rereads the current body. A definition whose name no longer matches that candidate is rejected and invalidates the exact provider for rediscovery.
```ts type-equiv
/** Caller context used for cwd-sensitive and abortable provider work. */
interface SkillLookupOptions {
@@ -143,7 +199,7 @@ interface SkillLookupOptions {
}
```
The registry owns only its discovery-cache bound. The local provider owns filesystem roots (`dshHome`, `agentsHome`, `customSkillDirs`, and optional `bundledSkillDir`/`DSH_BUNDLED_SKILL_DIR`). The consumer owns its catalog description bound.
The registry owns only its discovery-cache bound. The local provider owns filesystem roots (`dshHome`, `agentsHome`, `customSkillDirs`, and optional `bundledSkillDir`/`DSH_BUNDLED_SKILL_DIR`) plus watcher enablement, polling, stability, symlink, and project-capacity controls. The consumer owns its catalog description bound. Exact defaults and validation are in the generated [config catalog](../config-catalog.md).
```ts type-equiv
/** Skill registry configuration. */
@@ -155,6 +211,8 @@ interface Config {
## Session catalog and tool contract
`dsh-tool-skill` injects a durable user-role `<system-reminder>` at the first `agent/step` of a live session. The catalog contains sorted skill `name` and normalized, XML-escaped `description` only; it omits bodies, paths, sources, providers, and routing hints. Discovery forwards the step's abort signal through `SkillLookupOptions`. `catalogDescriptionMaxLength` is the consumer config for the description bound, with default `500` and integer minimum `3`.
`dsh-tool-skill` injects the initial durable user-role `<system-reminder>` at the first `agent/step` of a live session that observes a non-empty complete view. The catalog contains sorted skill `name` and normalized, XML-escaped `description` only; it omits bodies, paths, sources, providers, and routing hints. Discovery forwards the step's abort signal through `SkillLookupOptions`. `catalogDescriptionMaxLength` is the consumer config for the description bound, with default `500` and integer minimum `3`.
The model-facing `skill({ name })` tool validates the kebab-case name, loads the complete definition for the calling agent cwd, reports an unresolved skill as unknown or no longer available, rejects `disableModelInvocation` skills, and returns a tool result containing `<skill_content name="...">`, `<skill_resources>`, and `<skill_instructions>`. `resourceBase` resolves explicitly referenced scripts, references, and assets only as needed; the loaded result does not enumerate a skill directory. The tool result is the model-visible path for complete instructions.
Before each later model step, the consumer applies exact tool visibility and digests the exact rendered entries between the `<available_skills>` tags from a complete snapshot. It derives the comparison baseline from the same entries in the newest recognizable visible catalog message sourced by the plugin. A changed digest appends a durable full replacement through `agent.inject()`; deleting every skill appends an explicit empty replacement. Incomplete snapshots preserve the last-good model view. If compaction hides every historical catalog message, the next complete snapshot re-establishes the current catalog; an empty view with no prior catalog emits nothing. These catalog messages are session history, not World State.
The model-facing `skill({ name })` tool validates the kebab-case name, finds the summary in the invocation-neutral catalog, rejects it before loading unless `isModelInvocable` permits access, then rereads the complete definition for the calling agent cwd and rechecks the policy before returning content. It reports an unresolved skill as unknown or no longer available and returns a tool result containing `<skill_content name="...">`, `<skill_resources>`, and `<skill_instructions>`. `resourceBase` resolves explicitly referenced scripts, references, and assets only as needed; the loaded result does not enumerate a skill directory. Body-only edits therefore change later tool calls without producing catalog messages or rewriting earlier tool results.

View File

@@ -2,7 +2,7 @@
[English](skills.md) | 中文
[skill技能能力族](../../packages/skill)拆分为三个包package注册表[dsh-skill](../../packages/skill/skill)`ctx.skills`)合并各提供方的目录;本地提供方([dsh-skill-local](../../packages/skill/skill-local))扫描项目/自定义/用户目录;消费方([dsh-tool-skill](../../packages/skill/tool-skill))拥有会话前缀目录和面向模型的 `skill` 工具。skill 是可选的指令而非会话事件,因此其词汇定义在此处而非 [core.md](core.md)。
[skill技能能力族](../../packages/skill)拆分为三个包package注册表[dsh-skill](../../packages/skill/skill)`ctx.skills`)合并各提供方的目录;本地提供方([dsh-skill-local](../../packages/skill/skill-local))扫描并监视项目/自定义/用户目录;消费方([dsh-tool-skill](../../packages/skill/tool-skill))拥有初始目录和替换目录,以及面向模型的 `skill` 工具。skill 是可选的指令而非会话事件,因此其词汇定义在此处而非 [core.md](core.md)。
源码:[`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts)、[`packages/skill/skill-local/src/index.ts`](../../packages/skill/skill-local/src/index.ts) 与 [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts)。
@@ -10,7 +10,19 @@
`ctx.skills` 组合本地、内嵌、远程或其他提供方。注册是同步的;远程初始化与发现属于 `list()` 的 await 阶段。提供方对象、选项与候选项以只读方式借用,语义字段会被校验。
重名按 rank、提供方顺序、本地顺序依次解决摘要按名称排序。`list()` 拒绝时记录日志并跳过,不缓存降级后的目录;格式错误的候选项快速失败
重名按 rank、提供方顺序、本地顺序依次解决摘要按名称排序。`list()` 拒绝时记录日志并从不完整观测中省略;显式的不完整观测会提供可用候选项,但不会使结果变得可缓存;格式错误的候选项快速失败。每个提供方工厂都会接收一项注册作用域内的控制能力;仅当该精确注册仍处于活动状态时,其 `invalidate()` 才会清除已完成目录;注册失败或释放时,其信号会中止。若提供方代次在发现进行期间发生变化,该发现会重试一次;若再次变化,则返回最新候选项,并将结果标为不完整且不予缓存。提供方和运行时变更会发出不带过滤条件的 `skills/change` 失效事件;该事件不携带 diff因此消费方会使用自身的查找选项重新获取 `snapshot()`
`SkillProvider.list()` 返回的数组是完整发现的简写形式。`SkillProviderObservation` 允许提供方公开仍可直接加载的候选项,同时报告该观测不具权威性。
```ts type-equiv
/** Provider candidates plus whether the current discovery is authoritative. */
interface SkillProviderObservation {
/** Candidates available from the current provider discovery. */
readonly candidates: readonly SkillCandidate[]
/** Whether discovery completed and these candidates may be cached. */
readonly complete: boolean
}
```
```ts type-equiv
/** Provider interface for one source of skills, such as local directories or a remote registry. */
@@ -23,9 +35,10 @@ interface SkillProvider {
* authentication, and discovery are awaited inside this method. Implementations
* should settle promptly when `options.signal` aborts.
* @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
* @returns provider candidates with precedence ranks and opaque locators.
* @returns provider candidates as a complete-array shorthand, or an explicit
* observation when usable candidates came from incomplete discovery.
*/
readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[]>
readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[] | SkillProviderObservation>
/**
* Load a complete skill body for a previously listed candidate.
* @param candidate - the winning candidate originally returned by this provider.
@@ -36,6 +49,16 @@ interface SkillProvider {
}
```
```ts type-equiv
/** Registration-scoped lifecycle and invalidation capability borrowed by one provider. */
interface SkillProviderControl {
/** Aborts if registration fails or when the exact provider registration is disposed. */
readonly signal: AbortSignal
/** Invalidate completed catalogs and notify consumers only while the exact registration remains active. */
readonly invalidate: () => void
}
```
## 本地发现优先级
内置的本地提供方按 rank 顺序扫描各根目录:
@@ -51,6 +74,8 @@ interface SkillProvider {
项目根目录为包含 `.git` 的最近祖先目录;找不到时使用当前 cwd。当 `ctx.fs` 可用时git-root 向上查找通过文件系统服务探测 `.git`,使远程或沙箱工作区不会回退到宿主文件系统边界。用户 DSH 根目录会跳过其 `.system` 子目录。本地提供方不附带内置系统 skill部署方通过另一个提供方提供内置 skill。
Chokidar 会监视现有根目录中直属 bundle 和平铺条目的添加与移除,以及直属 skill 条目的变更。缺失的根目录会从最近的现有祖先开始,逐个跟踪缺失路径段,直至 Chokidar 可以附加。bundle 下的资源文件变更不属于目录变更。面向模型的 `write` 和 `edit` 观测会在目标路径相关时同步使提供方目录失效,而宿主 watcher 覆盖 IDE、Git、shell 和外部进程产生的变更。watcher 失败会使当前观测不完整,但不会在直接加载时隐藏可读候选项;项目作用域 watcher 使用按配置设限的 LRU。
## Skill 身份
skill 名称为 kebab-case`^[a-z0-9]+(?:-[a-z0-9]+)*$`)。本地提供方接受目录包(`<name>/SKILL.md`)和扁平 Markdown 文件(`<name>.md`)。嵌套递归的 `**/SKILL.md` 发现有意不在 v1 范围内。
@@ -62,19 +87,29 @@ type SkillSource = 'project-dsh' | 'project-agents' | 'runtime' | 'user-dsh' | '
## 摘要、候选项与完整定义
`SkillSummary` 是注册表中可供模型调用的摘要形状。消费方自行选择渲染哪些字段;会话目录仅使用 `name` 和 `description`,从不使用 body 或绝对文件路径。`disableModelInvocation` 将 skill 从模型列表中隐藏,但允许受信代码按名称加载
`SkillSummary` 是注册表中与调用策略无关的摘要形状。消费方自行选择渲染哪些条目和字段;模型会话目录仅使用模型可调用 skill 的 `name` 和 `description`,从不使用正文或绝对文件路径。`SkillInvocationPolicy` 将两个独立调用控制规范化为正向布尔值,且每个已解析的摘要、候选项和定义都携带该策略,而不会把任意 frontmatter 纳入领域模型
```ts type-equiv
/** Model-visible skill metadata returned by `ctx.skills.list()` and rendered into request guidance. */
/** Invocation controls shared by skill discovery consumers. */
interface SkillInvocationPolicy {
/** Whether model-facing catalogs and loaders include this skill. */
readonly modelInvocable: boolean
/** Whether human-facing command catalogs and loaders include this skill. */
readonly userInvocable: boolean
}
```
```ts type-equiv
/** Invocation-neutral skill metadata returned by `ctx.skills.list()`. */
interface SkillSummary {
/** Kebab-case identifier used with the `skill` tool. */
/** Kebab-case identifier used to address the skill. */
readonly name: string
/** Short routing description shown to the model. */
/** Short routing description shown by discovery consumers. */
readonly description: string
/** Optional extra routing guidance shown to the model. */
/** Optional extra routing guidance. */
readonly whenToUse?: string
/** Whether the skill is hidden from model listings while remaining loadable by trusted callers. */
readonly disableModelInvocation?: boolean
/** Resolved model and user invocation controls. */
readonly invocation: SkillInvocationPolicy
/** Discovery source that produced this winning skill. */
readonly source: SkillSource
/** Provider that owns this skill body. */
@@ -84,6 +119,20 @@ interface SkillSummary {
}
```
`ctx.skills.list()` 保留全部四种策略组合。`isModelInvocable(skill)` 和 `isUserInvocable(skill)` 分别读取对应的必填字段。仅供模型调用的 skill 设置 `{ modelInvocable: true, userInvocable: false }`,仅供用户调用的 skill 设置 `{ modelInvocable: false, userInvocable: true }`,两个字段均设为 `false` 后,该 skill 只能由受信的 `ctx.skills.get()` 调用方获取。本地提供方读取名称完全匹配的 kebab-case frontmatter 键 `disable-model-invocation` 和 `user-invocable`,将省略的字段默认为 `true`,并为每个解析出的 skill 生成这个规范化策略。
`SkillCatalogSnapshot` 用于区分已确定的不存在与提供方的瞬时失败或发现期间持续变化的目录。`skills` 包含该次观测中收集、排序且与调用策略无关的摘要;只有每个已注册提供方都在没有并发目录修订时完成发现,`complete` 才为 true。不完整快照不会缓存因此每个消费方可以保留上一份经过自身过滤的可用目录并重试。
```ts type-equiv
/** One catalog observation plus whether discovery completed within a stable catalog revision. */
interface SkillCatalogSnapshot {
/** Sorted invocation-neutral summaries collected in this observation. */
readonly skills: SkillSummary[]
/** Whether every registered provider completed without a concurrent catalog revision. */
readonly complete: boolean
}
```
`SkillCandidate` 是提供方到注册表的形状。`locator` 是提供方的不透明状态;注册表只存储它并在调用获胜提供方的 `get()` 时传回。
```ts type-equiv
@@ -122,17 +171,24 @@ interface SkillDefinition extends SkillSummary {
}
```
运行时 skill 使用相同的完整形状,参与相同的先到先得收集顺序。返回的 disposer 移除该贡献并使发现缓存失效。
运行时 skill 输入可以省略调用控制和提供方标签。注册表会一次性补全这两项默认值,随后使用与提供方相同的完整定义形状和先到先得收集顺序。返回的 disposer 移除该贡献并使发现缓存失效。
```ts type-equiv
/** Runtime skill contribution accepted by `ctx.skills.register()`. */
type SkillRegistration = Omit<SkillDefinition, 'provider'> & { readonly provider?: string }
type SkillRegistration = Omit<SkillDefinition, 'invocation' | 'provider'> & {
/** Invocation controls; omission permits both model and user surfaces. */
readonly invocation?: SkillInvocationPolicy
/** Provider label; omission uses the registry-owned runtime provider. */
readonly provider?: string
}
```
## 查找与配置
skill 查找对 cwd 敏感,因为提供方可能暴露工作区本地的 skill可选的 signal 为调用方取消提供方的工作。提供方接收与缓存标识和加载相同的只读选项对象。取消在目录选择前后(包括缓存命中时)都会检查,并与发现和完整定义加载竞争。如果找不到 git root本地提供方将所提供的 cwd 本身视为项目根目录。
注册表不缓存完整定义。每次调用 `get()` 都会携所选候选项调用胜出提供方,因此本地提供方会重新读取当前正文。名称与该候选项不再匹配的定义会被拒绝,并使该提供方实例失效以便重新发现。
```ts type-equiv
/** Caller context used for cwd-sensitive and abortable provider work. */
interface SkillLookupOptions {
@@ -143,7 +199,7 @@ interface SkillLookupOptions {
}
```
注册表只拥有其发现缓存上限。本地提供方拥有文件系统根目录(`dshHome`、`agentsHome`、`customSkillDirs`,以及可选的 `bundledSkillDir`/`DSH_BUNDLED_SKILL_DIR`。消费方拥有其目录描述上限
注册表只拥有其发现缓存上限。本地提供方拥有文件系统根目录(`dshHome`、`agentsHome`、`customSkillDirs`,以及可选的 `bundledSkillDir`/`DSH_BUNDLED_SKILL_DIR`,以及 watcher 启用、轮询、稳定性、符号链接和项目容量控制。消费方拥有其目录描述上限。确切的默认值和校验规则见自动生成的[插件配置目录](../config-catalog.md)
```ts type-equiv
/** Skill registry configuration. */
@@ -155,6 +211,8 @@ interface Config {
## 会话目录与工具契约
`dsh-tool-skill` 在存活会话第一个 `agent/step` 注入一条持久 user-role `<system-reminder>`。目录只包含已排序的 skill `name` 和规范化、经 XML 转义的 `description`;不包含正文、路径、来源、提供方或路由提示。发现通过 `SkillLookupOptions` 转发该步骤的 abort signal。`catalogDescriptionMaxLength` 是消费方用于 description 上限的配置,默认值为 `500`,整数最小值为 `3`。
`dsh-tool-skill` 在存活会话第一个观察到非空完整视图的 `agent/step` 注入初始的持久 user-role `<system-reminder>`。目录只包含已排序的 skill `name` 和规范化、经 XML 转义的 `description`;不包含正文、路径、来源、提供方或路由提示。发现通过 `SkillLookupOptions` 转发该步骤的 abort signal。`catalogDescriptionMaxLength` 是消费方用于 description 上限的配置,默认值为 `500`,整数最小值为 `3`。
面向模型的 `skill({ name })` 工具校验 kebab-case 名称,为调用方 agent 的 cwd 加载完整定义,将未解析的 skill 报告为 unknown 或 no longer available拒绝 `disableModelInvocation` 的 skill并返回包含 `<skill_content name="...">`、`<skill_resources>` 和 `<skill_instructions>` 的工具结果。`resourceBase` 仅按需解析显式引用的脚本、参考资料和资产;加载结果不枚举 skill 目录。工具结果是模型获取完整指令的可见路径。
在后续每个模型步骤之前,消费方都会应用精确的工具可见性,并对完整快照中 `<available_skills>` 标签之间精确渲染的条目计算 digest。它以该插件所发布、最新一条可识别且仍可见的目录消息中的相同条目作为比较基线。digest 发生变化时,会通过 `agent.inject()` 追加一条持久的完整目录替换;删除所有 skill 时会追加一条显式的空替换。不完整快照会保留上一份可用模型视图。如果压缩compaction隐藏了所有历史目录消息下一份完整快照会重新建立当前目录如果视图为空且从未发布目录则不发送任何内容。这些目录消息属于会话历史而非 World State。
面向模型的 `skill({ name })` 工具校验 kebab-case 名称,在与调用策略无关的目录中查找摘要,并在加载前通过 `isModelInvocable` 拒绝无权访问的 skill随后它为调用方 agent 的 cwd 重新读取完整定义,并在返回内容前再次检查策略。该工具将未解析的 skill 报告为 unknown 或 no longer available并返回包含 `<skill_content name="...">`、`<skill_resources>` 和 `<skill_instructions>` 的工具结果。`resourceBase` 仅按需解析显式引用的脚本、参考资料和资产;加载结果不枚举 skill 目录。因此,仅修改正文会改变后续工具调用,而不会生成目录消息或改写先前工具结果。

View File

@@ -1,6 +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
defensive-patterns.md: c69094db461048f5dbca5f8bdd1fb5581b08a962
defensive-patterns.zh.md: eb57f035ad0bd67e62e285d451502d41e4efc2bc
# pnpm run verify-translation-pairing --write docs/defensive-patterns.md
defensive-patterns.md: cc34877fb0d6a2e1740d8fa138f879363c8e69a3
defensive-patterns.zh.md: 21b0977d8167ffecc21cdfab3c778efceefd8f03

View File

@@ -26,4 +26,4 @@ A user-supplied listener that throws must not reject the promise it runs inside
## Never hand untrusted output the ambient environment or predictable paths
Spawned commands get a scrubbed env (drop `*KEY*`/`*SECRET*`/`*TOKEN*`) so harness credentials cannot leak into output, `env`, or spill files. Temp/spill files use a private (0700) dir, random names, and exclusive owner-only opens (`'wx'`, `0o600`) — predictable world-readable paths invite symlink races and disclosure.
Spawned commands get a scrubbed env (drop `*KEY*`/`*SECRET*`/`*TOKEN*`/`*PASSWORD*`) so harness credentials cannot leak into output, `env`, or spill files. Temp/spill files use a private (0700) dir, random names, and exclusive owner-only opens (`'wx'`, `0o600`) — predictable world-readable paths invite symlink races and disclosure.

View File

@@ -26,4 +26,4 @@
## 绝不将环境变量或可预测路径暴露给不可信输出
spawn 的命令应获得一份经过清洗的 env去除 `*KEY*`/`*SECRET*`/`*TOKEN*`),使 harness 凭证无法泄漏到输出、`env` 或溢出文件中。临时/溢出文件应使用私有0700目录、随机文件名和排他的仅所有者可访问打开方式`'wx'``0o600`)——可预测的全局可读路径会招致符号链接竞争和信息泄露。
spawn 的命令应获得一份经过清洗的 env去除 `*KEY*`/`*SECRET*`/`*TOKEN*`/`*PASSWORD*`),使 harness 凭证无法泄漏到输出、`env` 或溢出文件中。临时/溢出文件应使用私有0700目录、随机文件名和排他的仅所有者可访问打开方式`'wx'``0o600`)——可预测的全局可读路径会招致符号链接竞争和信息泄露。

View File

@@ -21,13 +21,13 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| `agent/session-start` | `emit` | [`packages/core/agent/src/types.ts:299`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`workspace-context`](../packages/context/workspace-context) |
| `agent/settled` | `emit` | [`packages/core/agent/src/types.ts:387`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`compact-basic`](../packages/compact/compact-basic) |
| `agent/status` | `emit` | [`packages/core/agent/src/types.ts:236`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
| `agent/step` | `serial` | [`packages/core/agent/src/types.ts:326`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`compact-basic`](../packages/compact/compact-basic), [`plan-mode`](../packages/plan/plan-mode), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`time-context`](../packages/context/time-context), [`tool-skill`](../packages/skill/tool-skill), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
| `agent/step` | `serial` | [`packages/core/agent/src/types.ts:326`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`compact-basic`](../packages/compact/compact-basic), [`plan-mode`](../packages/plan/plan-mode), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/types.ts:373`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
| `approval/request` | `waterfall` | [`packages/ui/user-approval/src/index.ts:30`](../packages/ui/user-approval/src/index.ts) | [`user-approval`](../packages/ui/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `apiproxy` |
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:154`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | `apiproxy`, [`tui`](../packages/ui/tui) |
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `apiproxy`, [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace) |
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:62`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:71`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`) | [`fs-policy`](../packages/fs/fs-policy) |
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:71`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`) | [`fs-policy`](../packages/fs/fs-policy), [`skill-local`](../packages/skill/skill-local) |
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:54`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
| `goal/changed` | `emit` | [`packages/goal/goal/src/domain.ts:135`](../packages/goal/goal/src/domain.ts) | [`goal`](../packages/goal/goal) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:58`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/support/llm-replay), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`session-title`](../packages/session-title/session-title) |
@@ -35,10 +35,11 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:81`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session-persistence/session-persistence), [`session-projection-cache`](../packages/session-projection/session-projection-cache), [`session-telemetry`](../packages/telemetry/session-telemetry), [`session-title`](../packages/session-title/session-title) |
| `session/event` | `emit` | [`packages/core/session/src/index.ts:93`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), `apiproxy`, [`cli-demo`](../packages/examples/cli-demo), [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-projection`](../packages/session-projection/session-projection), [`session-projection-cache`](../packages/session-projection/session-projection-cache), [`session-telemetry`](../packages/telemetry/session-telemetry), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:103`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session-persistence/session-persistence), [`session-telemetry`](../packages/telemetry/session-telemetry) |
| `slash/input-begin-command` | `bail` | [`packages/client/ui-slash/src/types.ts:230`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `slash/input-consume-token` | `bail` | [`packages/client/ui-slash/src/types.ts:244`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `slash/input-insert-reference` | `bail` | [`packages/client/ui-slash/src/types.ts:237`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `slash/input-insert-text` | `bail` | [`packages/client/ui-slash/src/types.ts:252`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:188`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | [`tui`](../packages/ui/tui) |
| `slash/input-begin-command` | `bail` | [`packages/client/ui-slash/src/types.ts:232`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `slash/input-consume-token` | `bail` | [`packages/client/ui-slash/src/types.ts:246`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `slash/input-insert-reference` | `bail` | [`packages/client/ui-slash/src/types.ts:239`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `slash/input-insert-text` | `bail` | [`packages/client/ui-slash/src/types.ts:254`](../packages/client/ui-slash/src/types.ts) | - | `ui-conversation` |
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:140`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`jsonrpc`](../packages/ui/jsonrpc), [`subagent`](../packages/subagent/subagent) |
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:114`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:120`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
@@ -65,7 +66,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| --- | --- | --- |
| `commands/changed` | `runtime` (`emit`) | `ui-command` |
| `connection/reset` | `runtime` (`emit`) | `ui-command` |
| `internal/dispatch` | - | [`commands`](../packages/ui/commands), [`compact`](../packages/compact/compact), [`fs`](../packages/fs/fs), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/ui/permission), [`plan-mode`](../packages/plan/plan-mode), [`pty-local`](../packages/pty/pty-local), `runtime`, [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval), [`workflow`](../packages/workflow/workflow) |
| `internal/dispatch` | - | [`commands`](../packages/ui/commands), [`compact`](../packages/compact/compact), [`fs`](../packages/fs/fs), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/ui/permission), [`plan-mode`](../packages/plan/plan-mode), [`pty-local`](../packages/pty/pty-local), `runtime`, [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-title`](../packages/session-title/session-title), [`subagent`](../packages/subagent/subagent), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval), [`workflow`](../packages/workflow/workflow) |
| `internal/plugin` | - | `hmr`, `modules`, `webserver` |
| `internal/status` | - | [`agent`](../packages/core/agent) |
| `locale/change` | `locale` (`emit`) | `locale`, `ui-models`, `ui-settings-general` |

View File

@@ -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/i18n/README.md
README.md: 9fe01174909f0400b94c70b95759526aec783d2e
README.zh.md: 2a9a20ae4702e205879f0fbfb6d76d3a761d2446
README.md: d1fff61a1d3db7fbe93d3c95b144598c2ca41c8b
README.zh.md: 9f1d61f1b854ead0ef5851157cce2e9a6de83d89

View File

@@ -15,7 +15,7 @@ This repo's documentation is read by people and agents both inside and outside t
foo.zh.md: 89e6c98d92887913cadf06b2adb97f26cde4849b
```
Blob hashes, not commit hashes, so the record is computable for files edited in the same PR (`git hash-object foo.md`) and consistency is a pure content comparison. The recorded hashes also recover the exact last-confirmed text of either side, so an out-of-sync pair is updated by patching the counterpart minimally against the edited side's diff — never by re-translating whole files. `pnpm run gen-translation-brief <pair>` assembles that update's working set mechanically at the narrowest safely aligned granularity — changed Markdown units, then heading sections, then whole document — with the edited side's diff since last confirmation, each changed span's three-way text, the terminology rows the change touches, and the binding update rules; a change confined to the pair's byte-identical code fences is computed outright, and `--apply` splices it into the counterpart after structural validation ([briefed-updates Agent Note](../../.agents/notes/implemented/process/2026-07-26-briefed-minimal-translation-updates.md)). After bringing the pair back in line, `pnpm run verify-translation-pairing --write <pair>` re-records both hashes; that yaml diff is the reviewable act of confirming consistency, which is why `--write` requires naming the pairs you confirmed (`--write --all` is the explicit corpus-wide form).
Blob hashes, not commit hashes, so the record is computable for files edited in the same PR (`git hash-object foo.md`) and consistency is a pure content comparison. `--write` stores those snapshots in the local Git object database before recording them, including uncommitted working-tree contents, and pins every distinct stored blob under a content-addressed `refs/dsh/translation-pairing/snapshots/` ref so garbage collection cannot invalidate a recorded recovery pointer. The recorded hashes therefore recover the exact last-confirmed text of either side, so an out-of-sync pair is updated by patching the counterpart minimally against the edited side's diff — never by re-translating whole files. `pnpm run gen-translation-brief <pair>` assembles that update's working set mechanically at the narrowest safely aligned granularity — changed Markdown units, then heading sections, then whole document — with the edited side's diff since last confirmation, each changed span's three-way text, the terminology rows the change touches, and the binding update rules; a change confined to the pair's byte-identical code fences is computed outright, and `--apply` splices it into the counterpart after structural validation ([briefed-updates Agent Note](../../.agents/notes/implemented/process/2026-07-26-briefed-minimal-translation-updates.md)). After bringing the pair back in line, `pnpm run verify-translation-pairing --write <pair>` re-records both hashes; that yaml diff is the reviewable act of confirming consistency, which is why `--write` requires naming the pairs you confirmed (`--write --all` is the explicit corpus-wide form).
- **Language switcher.** Both files link to each other immediately after their H1 heading: the English file carries `English | [中文](foo.zh.md)` and the Chinese file carries `[English](foo.md) | 中文`.
- **Structure mirrors the counterpart.** Heading depths and order, list kinds, ordered-list starts, list item counts, table row and column counts, link targets, and verbatim code blocks match one to one across the pair — see [translation-rules.md](translation-rules.md) for the full preservation rules. Existing Markdown gates apply to `.zh.md` files unchanged (`verify-md-wrap`, `verify-md-links`).

View File

@@ -15,7 +15,7 @@
foo.zh.md: 89e6c98d92887913cadf06b2adb97f26cde4849b
```
用 blob hash 而不是 commit hash这样同一个 PR 里改动的文件也能算出记录(`git hash-object foo.md`),一致性是纯内容比较。记录的 hash 能还原任一侧上次确认时的确切文本,所以失去同步的配对是「按被改一侧的 diff 最小化地修补另一侧」,从不整篇重译。`pnpm run gen-translation-brief <pair>` 会以能安全对齐的最窄粒度——先是有改动的 Markdown 单元,再是标题小节,最后是整篇文档——机械地汇集这次更新的工作集:被改一侧自上次确认以来的 diff、每个改动块的三方文本、改动触及的术语表行以及有约束力的更新规则仅落在配对中逐字节一致的围栏代码块内的改动可以直接算出`--apply` 则经结构签名校验后把它拼接进对侧文件([briefed-updates Agent Note](../../.agents/notes/implemented/process/2026-07-26-briefed-minimal-translation-updates.md))。两侧对齐后,`pnpm run verify-translation-pairing --write <pair>` 重新记录两个 hash那份 yaml diff 就是「确认一致」这个动作本身,可以被评审,也正因如此,`--write` 要求点名你确认过的配对(`--write --all` 是显式的全语料形式)。
用 blob hash 而不是 commit hash这样同一个 PR 里改动的文件也能算出记录(`git hash-object foo.md`),一致性是纯内容比较。`--write` 会先把这些快照存入本地 Git 对象库再写下记录,未提交的工作树内容也不例外;它还会在内容寻址的 `refs/dsh/translation-pairing/snapshots/` ref 下固定每个不同的已存 blob使垃圾回收无法让已记录的恢复指针失效。因此记录的 hash 能还原任一侧上次确认时的确切文本,所以失去同步的配对是「按被改一侧的 diff 最小化地修补另一侧」,从不整篇重译。`pnpm run gen-translation-brief <pair>` 会以能安全对齐的最窄粒度——先是有改动的 Markdown 单元,再是标题小节,最后是整篇文档——机械地汇集这次更新的工作集:被改一侧自上次确认以来的 diff、每个改动块的三方文本、改动触及的术语表行以及有约束力的更新规则仅落在配对中逐字节一致的围栏代码块内的改动可以直接算出`--apply` 则经结构签名校验后把它拼接进对侧文件([briefed-updates Agent Note](../../.agents/notes/implemented/process/2026-07-26-briefed-minimal-translation-updates.md))。两侧对齐后,`pnpm run verify-translation-pairing --write <pair>` 重新记录两个 hash那份 yaml diff 就是「确认一致」这个动作本身,可以被评审,也正因如此,`--write` 要求点名你确认过的配对(`--write --all` 是显式的全语料形式)。
- **语言切换行。** 两个文件在各自 H1 标题之后立即互链:英文文件带 `English | [中文](foo.zh.md)`,中文文件带 `[English](foo.md) | 中文`。
- **结构与另一侧一一对应。** 标题深度与顺序、列表类型、有序列表起始编号、列表项数量、表格行列数、链接目标与逐字节一致的代码块在配对两侧一一对应;完整保持规则见 [translation-rules.md](translation-rules.md)。既有 Markdown 门禁对 `.zh.md` 文件原样生效(`verify-md-wrap`、`verify-md-links`)。

View File

@@ -54,7 +54,7 @@
| Round | Round | | 回合、目标回合、Ralph 回合 | 外层策略使用 Round 时,领域层级为 Session > Round > Turn轮次 > Step步骤Round 是可选的外层策略迭代并非每个会话轮次都具有的通用层级。Goal Round 与 Ralph Round 均保留英文。一个 Round 承载一个轮次,步骤隶属于该轮次;明确的零步骤轮次仍保持原义。 |
| schema | schema | | | |
| schema DSL | schema DSL | | | |
| seam | seam | | | 与 `extension point` 是不同概念;根据具体语境,可译为`服务边界``可替换点` |
| seam | seam | | 接缝 | 与 `extension point` 是不同概念;根据具体语境,可译为`服务边界``可替换点` |
| skill | skill | skill技能 | | |
| spawn | spawn | | | |
| steering | steering | steering中途引导 | | |
@@ -74,21 +74,24 @@
| adapter | 适配器 | | | |
| adapter contract | 适配器契约 | 适配器契约adapter contract | | |
| append-only | 仅追加 | | | |
| artifact | 产物 | | | |
| artifact | 产物 | | 制品 | |
| backend | 后端 | | | |
| background task | 后台任务 | | | |
| block | 块 | | | |
| build target | 构建目标 | | | |
| cancel | 取消 | | | |
| canary test | canary 测试 | | 金丝雀测试 | 本仓库保留 `canary` |
| capability seam | 能力 seam | | 功能 seam、能力接缝 | 本仓库接口、实现与消费方分离的命名架构概念;普通 `seam` 仍按其词条处理 |
| feature | 功能 | | 能力 | SDK 产品与工程模型中的可管理产品单元 |
| feature option | 功能选项 | | variant | 一项 SDK 功能内有限、可选择的实现或配置 |
| checkpoint | 检查点 | | | |
| chunk | 分片 | | | |
| compaction | 压缩 | 压缩compaction | | |
| companion tool | 配套工具 | | | |
| composition bundle | 组合包 | | | 只约束应用或插件的组合语境,不约束所有 `bundle` |
| Cordis plugin config | Cordis 插件配置 | | | Cordis 插件公开的 `Config` 对象或配置结构 |
| config key | 配置键 | | | Cordis 插件配置中的单个字段 |
| consumer | 消费方 | | | |
| consumer | 消费方 | | 消费者 | |
| content block | 内容块 | | | |
| Cookbook | 实操手册 | | | 文档标题用语 |
| context | 上下文 | | | |
@@ -145,9 +148,10 @@
| persistence | 持久化 | | | |
| pipeline | 流水线 | | | |
| plugin | 插件 | | | |
| postmortem | 事故复盘 | 事故复盘postmortem | 事后分析、事故记录 | 事故记录与分析文档;目录或路径中的 `postmortem` 保持代码形式 |
| prompt | 提示词 | | | |
| provider | 提供方 | | | |
| provider-neutral | 提供方无关 | | | |
| provider-neutral | 提供方无关 | | 提供方中立 | |
| quality gate | 质量门禁 | | | |
| quiescence | 完全停稳 | | 静默、静止状态 | 指生命周期工作全部结算后的状态 |
| reasoning | 推理 | 推理reasoning | | 需要和 `inference` 区分时保留英文括注 |
@@ -165,7 +169,7 @@
| sidecar record | 伴随记录 | | 旁挂记录 | 指与文档同目录的伴随记录文件 |
| smoke test | 冒烟测试 | | | |
| snapshot | 快照 | | | |
| source of truth | 真源 | | | |
| source of truth | 真源 | | 事实来源、唯一来源 | |
| spine | 主干 | | | |
| staged | 暂存 | | | 沿用 git 官方中文翻译 |
| stale | 陈旧 | | 过期 | 与 `fresh``新鲜`)成对;门禁输出中保留英文 `stale` 不翻译;`expired` 才译为`过期` |

View File

@@ -173,6 +173,7 @@ flowchart TD
subgraph group_context["packages/context"]
pkg_session_reference["session-reference"]
pkg_time_context["time-context"]
pkg_tmux_context["tmux-context"]
pkg_workspace_context["workspace-context"]
end
subgraph group_examples["packages/examples"]
@@ -264,7 +265,6 @@ flowchart TD
pkg_client_ui_primitives --> pkg_invariants
pkg_client_ui_question --> pkg_invariants
pkg_client_ui_slots --> pkg_invariants
pkg_client_ui_trajectory --> pkg_invariants
pkg_client_web --> pkg_invariants
pkg_client_web_react --> pkg_invariants
pkg_code_runtime --> pkg_invariants
@@ -301,9 +301,8 @@ flowchart TD
pkg_client_ui_sidebar --> pkg_client_ui_primitives
pkg_client_ui_sidebar --> pkg_client_ui_slots
pkg_client_ui_sidebar --> pkg_invariants
pkg_client_ui_slash --> pkg_client_runtime
pkg_client_ui_slash --> pkg_client_ui_slots
pkg_client_ui_slash --> pkg_invariants
pkg_client_ui_trajectory --> pkg_client_ui_primitives
pkg_client_ui_trajectory --> pkg_invariants
pkg_client_ui_workspace --> pkg_client_runtime
pkg_client_ui_workspace --> pkg_client_ui_primitives
pkg_client_ui_workspace --> pkg_client_ui_slots
@@ -337,26 +336,17 @@ flowchart TD
pkg_system_prompt --> pkg_scope
pkg_web --> pkg_invariants
pkg_web --> pkg_llm
pkg_client_ui_conversation --> pkg_client_runtime
pkg_client_ui_conversation --> pkg_client_ui_primitives
pkg_client_ui_conversation --> pkg_client_ui_slash
pkg_client_ui_conversation --> pkg_client_ui_slots
pkg_client_ui_conversation --> pkg_invariants
pkg_client_ui_settings_general --> pkg_client_locale
pkg_client_ui_settings_general --> pkg_client_runtime
pkg_client_ui_settings_general --> pkg_client_ui_primitives
pkg_client_ui_settings_general --> pkg_client_ui_settings
pkg_client_ui_settings_general --> pkg_client_ui_slots
pkg_client_ui_settings_general --> pkg_invariants
pkg_client_ui_skill --> pkg_client_connection
pkg_client_ui_skill --> pkg_client_runtime
pkg_client_ui_skill --> pkg_client_ui_slash
pkg_client_ui_skill --> pkg_client_ui_slots
pkg_client_ui_skill --> pkg_invariants
pkg_client_ui_subagent --> pkg_client_runtime
pkg_client_ui_subagent --> pkg_client_ui_slash
pkg_client_ui_subagent --> pkg_client_ui_slots
pkg_client_ui_subagent --> pkg_invariants
pkg_client_ui_slash --> pkg_client_locale
pkg_client_ui_slash --> pkg_client_runtime
pkg_client_ui_slash --> pkg_client_ui_primitives
pkg_client_ui_slash --> pkg_client_ui_slots
pkg_client_ui_slash --> pkg_invariants
pkg_client_ui_theme --> pkg_client_locale
pkg_client_ui_theme --> pkg_client_runtime
pkg_client_ui_theme --> pkg_client_ui_primitives
@@ -421,17 +411,25 @@ flowchart TD
pkg_app_boot --> pkg_invariants
pkg_app_boot --> pkg_paths
pkg_app_boot --> pkg_system_prompt
pkg_client_ui_command --> pkg_client_connection
pkg_client_ui_command --> pkg_client_runtime
pkg_client_ui_command --> pkg_client_ui_conversation
pkg_client_ui_command --> pkg_client_ui_primitives
pkg_client_ui_command --> pkg_client_ui_slash
pkg_client_ui_command --> pkg_client_ui_slots
pkg_client_ui_command --> pkg_invariants
pkg_client_ui_conversation --> pkg_client_locale
pkg_client_ui_conversation --> pkg_client_runtime
pkg_client_ui_conversation --> pkg_client_ui_primitives
pkg_client_ui_conversation --> pkg_client_ui_slash
pkg_client_ui_conversation --> pkg_client_ui_slots
pkg_client_ui_conversation --> pkg_invariants
pkg_client_ui_layout --> pkg_client_runtime
pkg_client_ui_layout --> pkg_client_ui_slots
pkg_client_ui_layout --> pkg_client_ui_theme
pkg_client_ui_layout --> pkg_invariants
pkg_client_ui_skill --> pkg_client_connection
pkg_client_ui_skill --> pkg_client_runtime
pkg_client_ui_skill --> pkg_client_ui_slash
pkg_client_ui_skill --> pkg_client_ui_slots
pkg_client_ui_skill --> pkg_invariants
pkg_client_ui_subagent --> pkg_client_runtime
pkg_client_ui_subagent --> pkg_client_ui_slash
pkg_client_ui_subagent --> pkg_client_ui_slots
pkg_client_ui_subagent --> pkg_invariants
pkg_code_runtime_worker --> pkg_code_runtime
pkg_code_runtime_worker --> pkg_invariants
pkg_code_runtime_worker --> pkg_session
@@ -512,17 +510,20 @@ flowchart TD
pkg_user_interaction --> pkg_agent
pkg_user_interaction --> pkg_invariants
pkg_user_interaction --> pkg_llm
pkg_client_ui_model --> pkg_client_connection
pkg_client_ui_model --> pkg_client_runtime
pkg_client_ui_model --> pkg_client_ui_command
pkg_client_ui_model --> pkg_client_ui_conversation
pkg_client_ui_model --> pkg_client_ui_primitives
pkg_client_ui_model --> pkg_client_ui_slash
pkg_client_ui_model --> pkg_client_ui_slots
pkg_client_ui_model --> pkg_invariants
pkg_client_ui_command --> pkg_client_connection
pkg_client_ui_command --> pkg_client_runtime
pkg_client_ui_command --> pkg_client_ui_conversation
pkg_client_ui_command --> pkg_client_ui_primitives
pkg_client_ui_command --> pkg_client_ui_slash
pkg_client_ui_command --> pkg_client_ui_slots
pkg_client_ui_command --> pkg_invariants
pkg_time_context --> pkg_agent
pkg_time_context --> pkg_invariants
pkg_time_context --> pkg_session
pkg_tmux_context --> pkg_agent
pkg_tmux_context --> pkg_bash
pkg_tmux_context --> pkg_invariants
pkg_tmux_context --> pkg_session
pkg_pty --> pkg_agent
pkg_pty --> pkg_brand
pkg_pty --> pkg_invariants
@@ -607,6 +608,14 @@ flowchart TD
pkg_client_ui_goal --> pkg_client_ui_slots
pkg_client_ui_goal --> pkg_goal
pkg_client_ui_goal --> pkg_invariants
pkg_client_ui_model --> pkg_client_connection
pkg_client_ui_model --> pkg_client_runtime
pkg_client_ui_model --> pkg_client_ui_command
pkg_client_ui_model --> pkg_client_ui_conversation
pkg_client_ui_model --> pkg_client_ui_primitives
pkg_client_ui_model --> pkg_client_ui_slash
pkg_client_ui_model --> pkg_client_ui_slots
pkg_client_ui_model --> pkg_invariants
pkg_pty_local --> pkg_agent
pkg_pty_local --> pkg_invariants
pkg_pty_local --> pkg_pty
@@ -701,6 +710,7 @@ flowchart TD
pkg_plan_mode --> pkg_agent
pkg_plan_mode --> pkg_commands
pkg_plan_mode --> pkg_invariants
pkg_plan_mode --> pkg_llm
pkg_plan_mode --> pkg_session
pkg_plan_mode --> pkg_session_projection
pkg_plan_mode --> pkg_system_prompt
@@ -795,6 +805,7 @@ flowchart TD
pkg_tool_pty --> pkg_tools
pkg_tool_tasks --> pkg_agent
pkg_tool_tasks --> pkg_invariants
pkg_tool_tasks --> pkg_llm
pkg_tool_tasks --> pkg_retention
pkg_tool_tasks --> pkg_system_prompt
pkg_tool_tasks --> pkg_tasks
@@ -847,6 +858,7 @@ flowchart TD
pkg_tui --> pkg_session_reference
pkg_tui --> pkg_session_title
pkg_tui --> pkg_skill
pkg_tui --> pkg_subprocess
pkg_tui --> pkg_system_prompt
pkg_tui --> pkg_token_meter
pkg_tui --> pkg_tools
@@ -982,7 +994,6 @@ flowchart TD
| [`client-ui-primitives`](../packages/client/ui-primitives) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-question`](../packages/client/ui-question) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-slots`](../packages/client/ui-slots) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-web`](../packages/client/web) | `client` | [`invariants`](../packages/support/invariants) |
| [`client-web-react`](../packages/client/web-react) | `client` | [`invariants`](../packages/support/invariants) |
| [`code-runtime`](../packages/code-runtime/code-runtime) | `code-runtime` | [`invariants`](../packages/support/invariants) |
@@ -1000,7 +1011,7 @@ flowchart TD
| [`client-ui-models`](../packages/client/ui-models) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-settings`](../packages/client/ui-settings) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-sidebar`](../packages/client/ui-sidebar) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-slash`](../packages/client/ui-slash) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`client-ui-primitives`](../packages/client/ui-primitives), [`invariants`](../packages/support/invariants) |
| [`client-ui-workspace`](../packages/client/ui-workspace) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`helper`](../packages/sdk/helper) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`subprocess`](../packages/subprocess/subprocess) |
| [`telemetry`](../packages/sdk/telemetry) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
@@ -1013,10 +1024,8 @@ flowchart TD
| [`session`](../packages/core/session) | `core` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope) |
| [`system-prompt`](../packages/core/system-prompt) | `core` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope) |
| [`web`](../packages/web/web) | `web` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm) |
| [`client-ui-conversation`](../packages/client/ui-conversation) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-settings-general`](../packages/client/ui-settings-general) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-settings`](../packages/client/ui-settings), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-skill`](../packages/client/ui-skill) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-subagent`](../packages/client/ui-subagent) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-slash`](../packages/client/ui-slash) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-theme`](../packages/client/ui-theme) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`host-directory-picker-browse`](../packages/host/directory-picker-browse) | `host` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
| [`host-directory-picker-native`](../packages/host/directory-picker-native) | `host` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
@@ -1036,8 +1045,10 @@ flowchart TD
| [`session-persistence`](../packages/session-persistence/session-persistence) | `session-persistence` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
| [`llm-replay`](../packages/support/llm-replay) | `support` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
| [`app-boot`](../packages/ui/app-boot) | `ui` | [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`system-prompt`](../packages/core/system-prompt) |
| [`client-ui-command`](../packages/client/ui-command) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-conversation`](../packages/client/ui-conversation) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-layout`](../packages/client/ui-layout) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-theme`](../packages/client/ui-theme), [`invariants`](../packages/support/invariants) |
| [`client-ui-skill`](../packages/client/ui-skill) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-subagent`](../packages/client/ui-subagent) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | `code-runtime` | [`code-runtime`](../packages/code-runtime/code-runtime), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
| [`lsp-local`](../packages/lsp/lsp-local) | `lsp` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
| [`sandbox-local`](../packages/sandbox/sandbox-local) | `sandbox` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox) |
@@ -1058,8 +1069,9 @@ flowchart TD
| [`commands`](../packages/ui/commands) | `ui` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`scope`](../packages/core/scope), [`session`](../packages/core/session) |
| [`user-approval`](../packages/ui/user-approval) | `ui` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt) |
| [`user-interaction`](../packages/ui/user-interaction) | `ui` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm) |
| [`client-ui-model`](../packages/client/ui-model) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-command`](../packages/client/ui-command), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`client-ui-command`](../packages/client/ui-command) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`time-context`](../packages/context/time-context) | `context` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
| [`tmux-context`](../packages/context/tmux-context) | `context` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
| [`pty`](../packages/pty/pty) | `pty` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
| [`scripts`](../packages/sdk/scripts) | `sdk` | [`app-boot`](../packages/ui/app-boot), [`invariants`](../packages/support/invariants) |
| [`session-projection-cache`](../packages/session-projection/session-projection-cache) | `session-projection` | [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-projection`](../packages/session-projection/session-projection), [`storage-domain`](../packages/storage/storage-domain) |
@@ -1077,6 +1089,7 @@ flowchart TD
| [`acp`](../packages/acp/acp) | `acp` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`user-approval`](../packages/ui/user-approval) |
| [`permission`](../packages/ui/permission) | `ui` | [`bash`](../packages/bash/bash), [`commands`](../packages/ui/commands), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`session-projection`](../packages/session-projection/session-projection), [`user-approval`](../packages/ui/user-approval) |
| [`client-ui-goal`](../packages/client/ui-goal) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants) |
| [`client-ui-model`](../packages/client/ui-model) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-command`](../packages/client/ui-command), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`pty-local`](../packages/pty/pty-local) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`pty`](../packages/pty/pty), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess) |
| [`tasks-local`](../packages/tasks/tasks-local) | `tasks` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tasks`](../packages/tasks/tasks), [`timeout`](../packages/util/timeout) |
| [`session-telemetry-otel`](../packages/telemetry/session-telemetry-otel) | `telemetry` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-telemetry`](../packages/telemetry/session-telemetry) |
@@ -1091,7 +1104,7 @@ flowchart TD
| [`spill-policy`](../packages/spill/spill-policy) | `spill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`tools`](../packages/core/tools) |
| [`timeout-policy`](../packages/timeout/timeout-policy) | `timeout` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
| [`tool-todo`](../packages/todo/tool-todo) | `todo` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-projection`](../packages/session-projection/session-projection), [`tools`](../packages/core/tools) |
| [`plan-mode`](../packages/plan/plan-mode) | `plan` | [`agent`](../packages/core/agent), [`commands`](../packages/ui/commands), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-projection`](../packages/session-projection/session-projection), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
| [`plan-mode`](../packages/plan/plan-mode) | `plan` | [`agent`](../packages/core/agent), [`commands`](../packages/ui/commands), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session-projection/session-projection), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
| [`tool-cordis`](../packages/cordis/tool-cordis) | `cordis` | [`invariants`](../packages/support/invariants), [`scope`](../packages/core/scope), [`tools`](../packages/core/tools) |
| [`hooks-codex`](../packages/hooks/hooks-codex) | `hooks` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/hooks/hook-protocol), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`tools`](../packages/core/tools) |
| [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy) | `session-persistence` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`tools`](../packages/core/tools) |
@@ -1108,13 +1121,13 @@ flowchart TD
| [`tool-lsp`](../packages/lsp/tool-lsp) | `lsp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
| [`mcp-client`](../packages/mcp/mcp-client) | `mcp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subprocess`](../packages/subprocess/subprocess), [`tools`](../packages/core/tools) |
| [`tool-pty`](../packages/pty/tool-pty) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`pty`](../packages/pty/pty), [`retention`](../packages/util/retention), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`tool-tasks`](../packages/tasks/tool-tasks) | `tasks` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`retention`](../packages/util/retention), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`tool-tasks`](../packages/tasks/tool-tasks) | `tasks` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`tool-workflow`](../packages/workflow/tool-workflow) | `workflow` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
| [`subagent-acp`](../packages/subagent/subagent-acp) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess) |
| [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval) |
| [`tool-subagent`](../packages/subagent/tool-subagent) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`hooks-claude`](../packages/hooks/hooks-claude) | `hooks` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/hooks/hook-protocol), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
| [`tui`](../packages/ui/tui) | `ui` | [`agent`](../packages/core/agent), [`agent-loop`](../packages/core/agent-loop), [`commands`](../packages/ui/commands), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-query`](../packages/session-query/session-query), [`session-reference`](../packages/context/session-reference), [`session-title`](../packages/session-title/session-title), [`skill`](../packages/skill/skill), [`system-prompt`](../packages/core/system-prompt), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
| [`tui`](../packages/ui/tui) | `ui` | [`agent`](../packages/core/agent), [`agent-loop`](../packages/core/agent-loop), [`commands`](../packages/ui/commands), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-query`](../packages/session-query/session-query), [`session-reference`](../packages/context/session-reference), [`session-title`](../packages/session-title/session-title), [`skill`](../packages/skill/skill), [`subprocess`](../packages/subprocess/subprocess), [`system-prompt`](../packages/core/system-prompt), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
| [`client-ui-plan`](../packages/client/ui-plan) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`plan-mode`](../packages/plan/plan-mode) |
| [`agent-spine-demo`](../packages/examples/agent-spine-demo) | `examples` | [`agent`](../packages/core/agent), [`agent-loop`](../packages/core/agent-loop), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`paths`](../packages/util/paths), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-title`](../packages/session-title/session-title), [`skill`](../packages/skill/skill), [`skill-local`](../packages/skill/skill-local), [`system-prompt`](../packages/core/system-prompt), [`tasks-local`](../packages/tasks/tasks-local), [`tool-bash`](../packages/bash/tool-bash), [`tool-goal`](../packages/goal/tool-goal), [`tool-skill`](../packages/skill/tool-skill), [`tool-tasks`](../packages/tasks/tool-tasks), [`tools`](../packages/core/tools), [`workspace-context`](../packages/context/workspace-context) |
| [`sdk-protocol`](../packages/sdk/sdk-protocol) | `sdk` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |

View File

@@ -213,7 +213,7 @@ Source: [`packages/ui/commands/src/index.ts:132`](../packages/ui/commands/src/in
'compact/end': { turn: number; error?: string }
```
Source: [`packages/compact/compact/src/types.ts:40`](../packages/compact/compact/src/types.ts)
Source: [`packages/compact/compact/src/types.ts:44`](../packages/compact/compact/src/types.ts)
#### `compact/start` — log-only
@@ -235,6 +235,8 @@ Source: [`packages/compact/compact/src/types.ts:15`](../packages/compact/compact
*/
'compact/summary': {
summary: ContentBlock[]
/** Complete provider output before the backend's safe summary projection. */
rawOutput?: ContentBlock[]
shadowedRange: { start: number; end: number }
shadowedSeqs: number[]
shadowedTokenCount: number
@@ -249,10 +251,12 @@ Source: [`packages/compact/compact/src/types.ts:15`](../packages/compact/compact
model: string
/** The generation cap the summarize call sent, when one applied. */
maxTokens?: number
/** Provider-reported token usage for the summarization request, when emitted. */
usage?: TokenUsage
}
```
Types: [ContentBlock](core-data-structures/core.md)
Types: [ContentBlock](core-data-structures/core.md) · [TokenUsage](core-data-structures/llm-streaming.md)
Source: [`packages/compact/compact/src/types.ts:22`](../packages/compact/compact/src/types.ts)
@@ -412,7 +416,7 @@ Source: [`packages/sandbox/sandbox-policy/src/session-mode.ts:33`](../packages/s
Types: [SessionTitleEventData](core-data-structures/session-title.md)
Source: [`packages/session-title/session-title/src/index.ts:96`](../packages/session-title/session-title/src/index.ts)
Source: [`packages/session-title/session-title/src/index.ts:100`](../packages/session-title/session-title/src/index.ts)
#### `session/title-llm-request` — log-only

View File

@@ -1,6 +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
# pnpm run verify-translation-pairing --write docs/postmortem/README.md
README.md: df0e2fcb8540aeed005153dbecc451d781ca5ff1
README.zh.md: 2ce6de475c705b02cd9dabfb2181929d81478e2c
README.zh.md: e364ef30e342f8484a40f35e3970dea0f2f86ef3

View File

@@ -2,13 +2,13 @@
[English](README.md) | 中文
事故复盘:一个 bug 到达了它不该到达的地方(真实用户、已合并的 PRPull Request、已发布的版本值得关注的是*为什么我们的流程放过了它*,而不仅仅是那一行修复。
事故复盘记录的是:一个 bug 流入了不该流入的环节(真实用户、已合并的 PRPull Request、已发布的版本值得关注的是*为什么我们的流程放过了它*,而不仅仅是那一行修复。
事故复盘不是 [Agent Noteagent 决策记录)](../../.agents/notes/README.md)Agent Note 记录一个经过深思熟虑的设计决策及其被否决的替代方案,或提出未来工作)。它是一份回顾性的失败记录:什么坏了、机制是什么、为什么每道安全网都没拦住、以及了哪些具体防护措施使同类 bug 下次能被显式暴露
事故复盘不是 [Agent Noteagent 决策记录)](../../.agents/notes/README.md)Agent Note 记录一个经过深思熟虑的设计决策及其被否决的替代方案,或提出未来工作)。它是一份回顾性的失败记录:什么坏了、机制是什么、为什么每道安全网都没拦住、以及为此新增了哪些具体防护措施,以确保同类 bug 下次出现时会明确报错
当一个 bug 满足以下条件时,请撰写事故复盘:**隐蔽**(机制不显而易见,即使是细心的工程师也得费力重新推导)、**系统性**(逃逸的原因是测试/工具/约定的缺口,而非一次性的笔误)、**重新发现的代价高**它消耗了真实的调试时间且下次还会如此。请链接该事故复盘所推动建立的防护措施测试、AGENTS.md 规则、ADR
每篇事故复盘以一段**摘要**开头:一个简短段落,让忙碌的读者在三十秒内吸收要点——什么坏了、用直白的话说根因是什么、为什么逃逸了、持久的教训是什么——然后才是后续的详细「概述 / 时间线 / 根因 / 防护措施」各节。
每篇事故复盘以一段**摘要**开头:一个简短段落,让忙碌的读者在三十秒内吸收要点——什么坏了、用直白的话说根因是什么、为什么逃逸了、可长期沿用的教训是什么——然后才是后续的详细「概述 / 时间线 / 根因 / 防护措施」各节。
| # | 标题 |
|---|---|

View File

@@ -26,7 +26,7 @@ This table connects model-visible tool names to the plugin package and service s
| `@deepseek-ai/dsh-tool-goal` | `create_goal`, `get_goal`, `update_goal` | `ctx.tools`, `ctx.agents`, `ctx.goals`, `ctx.systemPrompt`, `a calling Agent in an authorized open turn` | `tool/call`, `user/message goal snapshot for mutations`, `tool/result` | - | create, edit, pause, and resume require direct-human root authority; complete and blocked also accept the exact current goal round. The default blocked lower bound is three admitted rounds. |
| `@deepseek-ai/dsh-tool-lsp` | `lsp` | `ctx.tools`, `ctx.lsp`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | The lsp tool keeps provider selection and language-server subprocesses behind ctx.lsp, so its model-visible schema stays stable across providers. Requires a registered provider (e.g. `@deepseek-ai/dsh-lsp-local`) at runtime; without one, a query returns the structured `LSP_UNAVAILABLE` error rather than changing the schema. |
| `@deepseek-ai/dsh-tool-ralph` | `ralph` | `ctx.tools`, `ctx.workflows`, `ctx.subagents`, `ctx.systemPrompt`, `a calling Agent (exec.agent parents every fresh round)` | `tool/call`, `tool/result`, `workflow and child session events during execution` | - | A fixed foreground workflow starts one fresh structured child per round; the model selects only the immutable objective and an optional round cap. |
| `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.tools`, `ctx.skills` | `tool/call`, `tool/result` | - | - |
| `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.tools`, `ctx.agents`, `ctx.skills` | `tool/call`, `tool/result`, `user/message replacement catalogs via agent.inject()` | - | - |
| `@deepseek-ai/dsh-tool-session-query` | `session_event_read`, `session_event_search`, `session_event_trace`, `session_search`, `session_trace` | `ctx.tools`, `ctx.systemPrompt`, `ctx.sessionQuery`, `a calling Agent for workspace authority` | `tool/call`, `tool/result` | - | The five read-only tools hide provider cursors and authorize every result from the immutable calling agent session. The package is opt-in; compositions that need enforced deadlines or bounded inline output also mount the generic timeout or spill policies. |
| `@deepseek-ai/dsh-tool-subagent` | `subagent` | `ctx.tools`, `ctx.subagents` | `tool/call`, `tool/result`, `child session events through the chosen provider` | `subagent`, `subagent_fork` | The registered tool name is the load-time `toolName` config (default `subagent`); the schema above is that default. The shipped example agents load this package once per subagent backend, so the model additionally sees `subagent_fork` (bound to the fork backend) with an identical schema — see `examples/tui-agent/cordis.yml` and `examples/acp-agent/cordis.yml`. |
| `@deepseek-ai/dsh-tool-tasks` | `task_kill`, `task_list`, `task_output` | `ctx.tools`, `ctx.tasks`, `ctx.systemPrompt` | `tool/call`, `tool/result`, `user/message via agent.inject() for background completion notices` | - | The kind-agnostic background-task control surface: background bash commands, PTY sends, and subagents are read, listed, and killed through the same three tools. Loading the plugin attaches the control surface that arms producers' `ctx.tasks.start()`. |