dsh-plugin-dev-kb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +56 -0
- package/cordis.patch.yml +12 -0
- package/kb/INDEX.md +210 -0
- package/kb/README.md +69 -0
- package/kb/extra/AGENTS.md +75 -0
- package/kb/extra/api-gateway.md +164 -0
- package/kb/extra/api-gateway.zh.md +164 -0
- package/kb/extra/cookbook/adding-a-vendored-package.md +59 -0
- package/kb/extra/cookbook/adding-a-vendored-package.zh.md +59 -0
- package/kb/extra/cookbook/maintaining-dsh-code-review.md +64 -0
- package/kb/extra/cookbook/maintaining-dsh-code-review.zh.md +64 -0
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
- package/kb/extra/defensive-patterns.md +33 -0
- package/kb/extra/defensive-patterns.zh.md +33 -0
- package/kb/extra/development.md +171 -0
- package/kb/extra/development.zh.md +171 -0
- package/kb/extra/event-producer-consumer.md +76 -0
- package/kb/extra/event-producer-consumer.zh.md +78 -0
- package/kb/extra/glossary.md +45 -0
- package/kb/extra/glossary.zh.md +45 -0
- package/kb/extra/graph-atlas.md +24 -0
- package/kb/extra/graph-atlas.zh.md +26 -0
- package/kb/extra/i18n/README.md +60 -0
- package/kb/extra/i18n/README.zh.md +60 -0
- package/kb/extra/i18n/style-samples.md +87 -0
- package/kb/extra/i18n/terminology.md +214 -0
- package/kb/extra/i18n/translation-prompt.md +263 -0
- package/kb/extra/i18n/translation-rules.md +69 -0
- package/kb/extra/i18n/translation-rules.zh.md +69 -0
- package/kb/extra/module-graph.md +1641 -0
- package/kb/extra/module-graph.zh.md +1643 -0
- package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +113 -0
- package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
- package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
- package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
- package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
- package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
- package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
- package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
- package/kb/extra/postmortem/README.md +18 -0
- package/kb/extra/postmortem/README.zh.md +18 -0
- package/kb/extra/rescope.md +53 -0
- package/kb/extra/rescope.zh.md +53 -0
- package/kb/extra/subsystems/attachment.md +125 -0
- package/kb/extra/subsystems/attachment.zh.md +125 -0
- package/kb/extra/subsystems/extensions.md +364 -0
- package/kb/extra/subsystems/extensions.zh.md +364 -0
- package/kb/extra/subsystems/feedback.md +266 -0
- package/kb/extra/subsystems/feedback.zh.md +266 -0
- package/kb/extra/testing.md +49 -0
- package/kb/extra/testing.zh.md +49 -0
- package/kb/extra/web-styling.md +25 -0
- package/kb/extra/web-styling.zh.md +25 -0
- package/kb/meta/search-index.json +1328 -0
- package/kb/meta/site-pages.txt +168 -0
- package/kb/meta/source.json +13 -0
- package/kb/meta/topics.md +75 -0
- package/kb/site/develop/basic/config.md +108 -0
- package/kb/site/develop/basic/index.md +146 -0
- package/kb/site/develop/basic/publish.md +185 -0
- package/kb/site/develop/basic/tool.md +54 -0
- package/kb/site/develop/cordis-tutorial/01-first-plugin.md +95 -0
- package/kb/site/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
- package/kb/site/develop/cordis-tutorial/03-services.md +98 -0
- package/kb/site/develop/cordis-tutorial/04-events.md +144 -0
- package/kb/site/develop/cordis-tutorial/05-config.md +84 -0
- package/kb/site/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +107 -0
- package/kb/site/develop/cordis-tutorial/index.md +62 -0
- package/kb/site/develop/framework/events.md +145 -0
- package/kb/site/develop/framework/index.md +139 -0
- package/kb/site/develop/framework/service.md +152 -0
- package/kb/site/develop/practice/index.md +157 -0
- package/kb/site/develop/practice/llm-adapter.md +190 -0
- package/kb/site/en/develop/basic/config.md +108 -0
- package/kb/site/en/develop/basic/index.md +146 -0
- package/kb/site/en/develop/basic/publish.md +185 -0
- package/kb/site/en/develop/basic/tool.md +54 -0
- package/kb/site/en/develop/cordis-tutorial/01-first-plugin.md +95 -0
- package/kb/site/en/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
- package/kb/site/en/develop/cordis-tutorial/03-services.md +98 -0
- package/kb/site/en/develop/cordis-tutorial/04-events.md +144 -0
- package/kb/site/en/develop/cordis-tutorial/05-config.md +84 -0
- package/kb/site/en/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +107 -0
- package/kb/site/en/develop/cordis-tutorial/index.md +60 -0
- package/kb/site/en/develop/framework/events.md +145 -0
- package/kb/site/en/develop/framework/index.md +139 -0
- package/kb/site/en/develop/framework/service.md +150 -0
- package/kb/site/en/develop/practice/index.md +157 -0
- package/kb/site/en/develop/practice/llm-adapter.md +190 -0
- package/kb/site/en/guide/providers-custom-form.png +0 -0
- package/kb/site/en/guide/providers-models-page.png +0 -0
- package/kb/site/en/guide/providers.md +100 -0
- package/kb/site/en/guide/python-sdk.md +106 -0
- package/kb/site/en/guide/quickstart.md +32 -0
- package/kb/site/en/index.md +8 -0
- package/kb/site/en/reference/agent-lifecycle.md +86 -0
- package/kb/site/en/reference/capability-seams.md +475 -0
- package/kb/site/en/reference/config-catalog.md +3155 -0
- package/kb/site/en/reference/cookbook/adding-a-conversation-node.md +235 -0
- package/kb/site/en/reference/cookbook/adding-a-package.md +120 -0
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +102 -0
- package/kb/site/en/reference/cookbook/adding-a-tool.md +96 -0
- package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +45 -0
- package/kb/site/en/reference/cookbook/extension-cookbook.md +131 -0
- package/kb/site/en/reference/cordis-api/context.md +368 -0
- package/kb/site/en/reference/cordis-api/events.md +211 -0
- package/kb/site/en/reference/cordis-api/fiber.md +379 -0
- package/kb/site/en/reference/cordis-api/inherited.md +43 -0
- package/kb/site/en/reference/cordis-api/registry.md +156 -0
- package/kb/site/en/reference/cordis-api/service.md +106 -0
- package/kb/site/en/reference/cordis-primer.md +46 -0
- package/kb/site/en/reference/index.md +131 -0
- package/kb/site/en/reference/persistence-catalog.md +949 -0
- package/kb/site/en/reference/subsystems/approval.md +173 -0
- package/kb/site/en/reference/subsystems/client-modules.md +121 -0
- package/kb/site/en/reference/subsystems/code-runtime.md +194 -0
- package/kb/site/en/reference/subsystems/commands.md +190 -0
- package/kb/site/en/reference/subsystems/compaction.md +241 -0
- package/kb/site/en/reference/subsystems/core.md +1073 -0
- package/kb/site/en/reference/subsystems/credentials.md +136 -0
- package/kb/site/en/reference/subsystems/filesystem.md +498 -0
- package/kb/site/en/reference/subsystems/goal.md +280 -0
- package/kb/site/en/reference/subsystems/index.md +58 -0
- package/kb/site/en/reference/subsystems/invariants.md +91 -0
- package/kb/site/en/reference/subsystems/jobs.md +293 -0
- package/kb/site/en/reference/subsystems/llm-streaming.md +920 -0
- package/kb/site/en/reference/subsystems/lsp.md +205 -0
- package/kb/site/en/reference/subsystems/permission-presets.md +134 -0
- package/kb/site/en/reference/subsystems/persistence.md +388 -0
- package/kb/site/en/reference/subsystems/plan.md +90 -0
- package/kb/site/en/reference/subsystems/sandbox.md +221 -0
- package/kb/site/en/reference/subsystems/schedule.md +189 -0
- package/kb/site/en/reference/subsystems/scope.md +62 -0
- package/kb/site/en/reference/subsystems/session-projection.md +265 -0
- package/kb/site/en/reference/subsystems/session-query.md +498 -0
- package/kb/site/en/reference/subsystems/session-reference.md +111 -0
- package/kb/site/en/reference/subsystems/session-telemetry.md +197 -0
- package/kb/site/en/reference/subsystems/session-title.md +207 -0
- package/kb/site/en/reference/subsystems/session.md +852 -0
- package/kb/site/en/reference/subsystems/settings.md +313 -0
- package/kb/site/en/reference/subsystems/shell.md +306 -0
- package/kb/site/en/reference/subsystems/skills.md +334 -0
- package/kb/site/en/reference/subsystems/spill.md +120 -0
- package/kb/site/en/reference/subsystems/storage.md +232 -0
- package/kb/site/en/reference/subsystems/subagent.md +737 -0
- package/kb/site/en/reference/subsystems/subprocess.md +327 -0
- package/kb/site/en/reference/subsystems/system-prompt.md +210 -0
- package/kb/site/en/reference/subsystems/terminal.md +187 -0
- package/kb/site/en/reference/subsystems/token-meter.md +93 -0
- package/kb/site/en/reference/subsystems/tools.md +723 -0
- package/kb/site/en/reference/subsystems/typert.md +339 -0
- package/kb/site/en/reference/subsystems/user-questions.md +181 -0
- package/kb/site/en/reference/subsystems/web-server.md +111 -0
- package/kb/site/en/reference/subsystems/web.md +202 -0
- package/kb/site/en/reference/subsystems/workflow.md +281 -0
- package/kb/site/en/reference/subsystems/workspace.md +231 -0
- package/kb/site/en/reference/tool-catalog.md +1877 -0
- package/kb/site/en/reference/tool-execution-pipeline.md +66 -0
- package/kb/site/guide/providers-custom-form.zh.png +0 -0
- package/kb/site/guide/providers-models-page.zh.png +0 -0
- package/kb/site/guide/providers.md +100 -0
- package/kb/site/guide/python-sdk.md +106 -0
- package/kb/site/guide/quickstart.md +32 -0
- package/kb/site/index.md +8 -0
- package/kb/site/reference/agent-lifecycle.md +86 -0
- package/kb/site/reference/capability-seams.md +475 -0
- package/kb/site/reference/config-catalog.md +3154 -0
- package/kb/site/reference/cookbook/adding-a-conversation-node.md +235 -0
- package/kb/site/reference/cookbook/adding-a-package.md +120 -0
- package/kb/site/reference/cookbook/adding-a-settings-card.md +102 -0
- package/kb/site/reference/cookbook/adding-a-tool.md +98 -0
- package/kb/site/reference/cookbook/adding-an-llm-adapter.md +45 -0
- package/kb/site/reference/cookbook/extension-cookbook.md +133 -0
- package/kb/site/reference/cordis-api/context.md +368 -0
- package/kb/site/reference/cordis-api/events.md +211 -0
- package/kb/site/reference/cordis-api/fiber.md +379 -0
- package/kb/site/reference/cordis-api/inherited.md +43 -0
- package/kb/site/reference/cordis-api/registry.md +156 -0
- package/kb/site/reference/cordis-api/service.md +106 -0
- package/kb/site/reference/cordis-primer.md +52 -0
- package/kb/site/reference/index.md +135 -0
- package/kb/site/reference/persistence-catalog.md +949 -0
- package/kb/site/reference/subsystems/approval.md +173 -0
- package/kb/site/reference/subsystems/client-modules.md +121 -0
- package/kb/site/reference/subsystems/code-runtime.md +194 -0
- package/kb/site/reference/subsystems/commands.md +190 -0
- package/kb/site/reference/subsystems/compaction.md +241 -0
- package/kb/site/reference/subsystems/core.md +1081 -0
- package/kb/site/reference/subsystems/credentials.md +136 -0
- package/kb/site/reference/subsystems/filesystem.md +498 -0
- package/kb/site/reference/subsystems/goal.md +280 -0
- package/kb/site/reference/subsystems/index.md +58 -0
- package/kb/site/reference/subsystems/invariants.md +91 -0
- package/kb/site/reference/subsystems/jobs.md +293 -0
- package/kb/site/reference/subsystems/llm-streaming.md +926 -0
- package/kb/site/reference/subsystems/lsp.md +205 -0
- package/kb/site/reference/subsystems/permission-presets.md +134 -0
- package/kb/site/reference/subsystems/persistence.md +388 -0
- package/kb/site/reference/subsystems/plan.md +90 -0
- package/kb/site/reference/subsystems/sandbox.md +221 -0
- package/kb/site/reference/subsystems/schedule.md +189 -0
- package/kb/site/reference/subsystems/scope.md +62 -0
- package/kb/site/reference/subsystems/session-projection.md +265 -0
- package/kb/site/reference/subsystems/session-query.md +498 -0
- package/kb/site/reference/subsystems/session-reference.md +111 -0
- package/kb/site/reference/subsystems/session-telemetry.md +197 -0
- package/kb/site/reference/subsystems/session-title.md +207 -0
- package/kb/site/reference/subsystems/session.md +854 -0
- package/kb/site/reference/subsystems/settings.md +313 -0
- package/kb/site/reference/subsystems/shell.md +306 -0
- package/kb/site/reference/subsystems/skills.md +334 -0
- package/kb/site/reference/subsystems/spill.md +120 -0
- package/kb/site/reference/subsystems/storage.md +232 -0
- package/kb/site/reference/subsystems/subagent.md +739 -0
- package/kb/site/reference/subsystems/subprocess.md +327 -0
- package/kb/site/reference/subsystems/system-prompt.md +210 -0
- package/kb/site/reference/subsystems/terminal.md +187 -0
- package/kb/site/reference/subsystems/token-meter.md +93 -0
- package/kb/site/reference/subsystems/tools.md +723 -0
- package/kb/site/reference/subsystems/typert.md +339 -0
- package/kb/site/reference/subsystems/user-questions.md +181 -0
- package/kb/site/reference/subsystems/web-server.md +111 -0
- package/kb/site/reference/subsystems/web.md +202 -0
- package/kb/site/reference/subsystems/workflow.md +281 -0
- package/kb/site/reference/subsystems/workspace.md +231 -0
- package/kb/site/reference/tool-catalog.md +1880 -0
- package/kb/site/reference/tool-execution-pipeline.md +66 -0
- package/package.json +40 -0
- package/scripts/rebuild-index.mjs +88 -0
- package/skills/dsh-plugin-dev-kb.md +66 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
---
|
|
2
|
+
editSource: "docs/subsystems/sandbox.md"
|
|
3
|
+
outline: [2,3]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Process Sandbox
|
|
7
|
+
|
|
8
|
+
The process-sandbox seam of [dsh-sandbox](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/sandbox/sandbox) wraps a same-world subprocess argv in a file-effect policy without coupling consumers to a platform runner. [dsh-sandbox-local](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/sandbox/sandbox-local) supplies Linux bwrap/Landlock, macOS Seatbelt, and the Windows ACL restricted-token backend; [dsh-bash-sandbox](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/shell/bash-sandbox) and [dsh-pwsh-sandbox](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/shell/pwsh-sandbox) consume it. Containers, microVMs, and remote execution are sibling implementations of whole capability seams, not providers of `ctx.sandbox`.
|
|
9
|
+
|
|
10
|
+
Source: [`packages/sandbox/sandbox/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/sandbox/sandbox/src/index.ts)
|
|
11
|
+
|
|
12
|
+
## Modes and enforcement
|
|
13
|
+
|
|
14
|
+
`SandboxMode` governs filesystem effects only. `read-only` asks the backend to deny writes — the POSIX runners additionally grant the `/dev/null` sink their shells require, while the Windows ACL runner grants no explicit writable root and reports partial enforcement for its ambient ACL gaps; `workspace-write` permits writes under the workspace root and the backend's promised temp area; `danger-full-access` bypasses confinement. Network and process visibility are outside this vocabulary.
|
|
15
|
+
|
|
16
|
+
```ts type-equiv
|
|
17
|
+
/**
|
|
18
|
+
* File-effect policy for confined processes. `read-only` permits only required
|
|
19
|
+
* sinks such as `/dev/null`; `workspace-write` also permits the workspace and a
|
|
20
|
+
* backend-defined temp area; `danger-full-access` bypasses confinement. Network
|
|
21
|
+
* and process visibility are outside this vocabulary.
|
|
22
|
+
*/
|
|
23
|
+
type SandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Only the first two modes can be sent to a provider. A `danger-full-access` consumer spawns its original argv and does not call `ctx.sandbox`.
|
|
27
|
+
|
|
28
|
+
```ts type-equiv
|
|
29
|
+
/** A confining (non-`danger-full-access`) mode — the modes a {@link SandboxPolicy} can carry. */
|
|
30
|
+
type ConfinedSandboxMode = Exclude<SandboxMode, 'danger-full-access'>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Enforcement is a reported fact. `full` means the backend governs every file effect promised by the mode; `partial` means an active backend or older kernel ABI governs only a subset, so consumers that require the absolute promise must reject or surface that distinction. Older Landlock ABIs and the Windows ACL runner's Everyone/hard-link boundaries are current partial cases.
|
|
34
|
+
|
|
35
|
+
```ts type-equiv
|
|
36
|
+
/**
|
|
37
|
+
* Enforcement completeness for this host. `partial` means an active backend or
|
|
38
|
+
* older kernel ABI cannot govern every promised file effect; callers requiring
|
|
39
|
+
* an absolute boundary must not treat it as `full`.
|
|
40
|
+
*/
|
|
41
|
+
type SandboxEnforcement = 'full' | 'partial'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Per-call policy
|
|
45
|
+
|
|
46
|
+
The complete execution policy is resolved and carried per capability call. It includes `danger-full-access` so a consumer can resolve policy once before deciding whether to bypass confinement. Normal tool calls derive `workspaceRoot` from the calling session's immutable cwd; deployment configuration is the agentless fallback. The root is canonicalized with filesystem semantics before lexical normalization, so a cwd containing `symlink/..` identifies the directory where a spawned process actually runs.
|
|
47
|
+
|
|
48
|
+
```ts type-equiv
|
|
49
|
+
/**
|
|
50
|
+
* The complete file-effect policy resolved for one capability call. The root
|
|
51
|
+
* is carried even under modes that do not consume it so callers can resolve
|
|
52
|
+
* policy once before choosing the enforcement path.
|
|
53
|
+
*/
|
|
54
|
+
interface SandboxExecutionPolicy {
|
|
55
|
+
/** The file-effect mode this execution runs under. */
|
|
56
|
+
mode: SandboxMode
|
|
57
|
+
/** Absolute root directory `workspace-write` may write under. */
|
|
58
|
+
workspaceRoot: string
|
|
59
|
+
/**
|
|
60
|
+
* Opaque identity of the calling session (the branded `dsh-session`
|
|
61
|
+
* SessionId). Backends key per-session state off it (e.g. windows-acl gives
|
|
62
|
+
* each live session/workspace pair a random private temp directory and SID,
|
|
63
|
+
* while the workspace SID and standing grant remain per-workspace); absent
|
|
64
|
+
* for agentless calls, which fall back to per-call backend state.
|
|
65
|
+
*/
|
|
66
|
+
sessionId?: SessionId
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`ctx.sandboxPolicy.resolve()` accepts the active session and, for an approved retry, an explicit mode. The service owns precedence and root fallback so bash and fs do not repeat it.
|
|
71
|
+
|
|
72
|
+
```ts type-equiv
|
|
73
|
+
/** Inputs that select the sandbox policy for one capability call. */
|
|
74
|
+
interface SandboxPolicyRequest {
|
|
75
|
+
/** Calling session; its immutable cwd becomes the workspace boundary. */
|
|
76
|
+
session?: Session
|
|
77
|
+
/** Explicit approved mode override, which outranks session policy. */
|
|
78
|
+
mode?: SandboxMode
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Only a confined execution reaches `ctx.sandbox`; its provider policy narrows the mode while retaining the same root. This permits concurrent sessions, consumers, and one-shot escalated retries to ask the same provider for different boundaries without mutating provider state.
|
|
83
|
+
|
|
84
|
+
```ts type-equiv
|
|
85
|
+
/**
|
|
86
|
+
* What one confined execution is allowed to touch — carried PER CALL, not
|
|
87
|
+
* fixed on the provider: two consumers may confine under different policies
|
|
88
|
+
* at the same instant (bash under `read-only` while a confined child agent
|
|
89
|
+
* needs its state directory writable), and an approved escalated retry is a
|
|
90
|
+
* new call with a wider policy. Defaulting/resolution is an explicit step at
|
|
91
|
+
* the consumer boundary; the provider treats the policy as fully specified.
|
|
92
|
+
*/
|
|
93
|
+
interface SandboxPolicy extends SandboxExecutionPolicy {
|
|
94
|
+
/** The file-effect mode this execution runs under. */
|
|
95
|
+
mode: ConfinedSandboxMode
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Wrapped argv and classification dialects
|
|
100
|
+
|
|
101
|
+
`RunnerFailureRule` combines evidence that a runner failed before executing the command. A consumer requires a nonzero exit, the optional allowed-exit-code gate, and a case-insensitive fatal signature within one remaining stderr line. Case-insensitive exact full-line informational exclusions are removed first, so a benign runner notice cannot prove failure by itself. The matched line remains available as error detail; classification does not rewrite stderr.
|
|
102
|
+
|
|
103
|
+
```ts type-equiv
|
|
104
|
+
/**
|
|
105
|
+
* Evidence that identifies a sandbox runner failing before it executes the
|
|
106
|
+
* wrapped command. A consumer first applies {@link allowedExitCodes} when
|
|
107
|
+
* present, removes {@link informationalLines} by case-insensitive exact line
|
|
108
|
+
* equality, then matches {@link fatalSignatures} case-insensitively within
|
|
109
|
+
* each remaining stderr line. Exit status alone never proves runner failure.
|
|
110
|
+
*/
|
|
111
|
+
interface RunnerFailureRule {
|
|
112
|
+
/** Nonzero process exit codes on which this rule may match; omitted permits any nonzero exit. */
|
|
113
|
+
allowedExitCodes?: readonly number[]
|
|
114
|
+
/** Non-empty substrings identifying a fatal runner diagnostic on one stderr line. */
|
|
115
|
+
fatalSignatures: readonly string[]
|
|
116
|
+
/** Benign stderr lines excluded by exact full-line equality before fatal matching. */
|
|
117
|
+
informationalLines?: readonly string[]
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`ConfinedArgv` is what the consumer spawns. Besides the replacement argv, it carries the backend's enforcement fact and two orthogonal stderr classifiers. `denialSignatures` identify the confined command being blocked while the sandbox works correctly. `runnerFailureRules` identify the sandbox runner refusing or failing before it executes the command; consumers check these first and surface a sandbox infrastructure failure, never an ordinary task failure.
|
|
122
|
+
|
|
123
|
+
```ts type-equiv
|
|
124
|
+
/**
|
|
125
|
+
* A {@link SandboxProvider.confine} result: the argv to spawn in place of
|
|
126
|
+
* the caller's own, plus the enforcement completeness the selected backend
|
|
127
|
+
* achieves for it.
|
|
128
|
+
*/
|
|
129
|
+
interface ConfinedArgv {
|
|
130
|
+
/** The wrapped argv (runner, profile, separator, then the caller's argv). */
|
|
131
|
+
argv: string[]
|
|
132
|
+
/** How completely the selected backend enforces the policy's file effects. */
|
|
133
|
+
enforcement: SandboxEnforcement
|
|
134
|
+
/**
|
|
135
|
+
* The selected backend's denial DIALECT: the case-insensitive stderr
|
|
136
|
+
* substrings a file effect denied by THIS backend produces (EROFS text
|
|
137
|
+
* under bwrap's read-only binds, EACCES under Landlock, EPERM under
|
|
138
|
+
* Seatbelt). A consumer that infers denials from a failed run's stderr
|
|
139
|
+
* matches against exactly these rather than a cross-backend union — the
|
|
140
|
+
* union claims denials a given backend never produces.
|
|
141
|
+
*/
|
|
142
|
+
denialSignatures: readonly string[]
|
|
143
|
+
/**
|
|
144
|
+
* Structured runner-failure evidence rules. Consumers require a matching
|
|
145
|
+
* fatal stderr line (after informational exclusions) and any rule-specific
|
|
146
|
+
* exit-code gate before checking denial signatures: runner failure means the
|
|
147
|
+
* command never ran, while denial means confinement worked and blocked it.
|
|
148
|
+
*/
|
|
149
|
+
runnerFailureRules: readonly RunnerFailureRule[]
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The [local provider](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/sandbox/sandbox-local/README.md) owns operator configuration and maps its runner dialect into these rules. The [sandboxed bash consumer](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/shell/bash-sandbox/README.md) owns spawn and result attribution.
|
|
154
|
+
|
|
155
|
+
## Provider and fail-closed errors
|
|
156
|
+
|
|
157
|
+
`ctx.sandbox.confine(argv, policy)` returns a `ConfinedArgv` or throws `SandboxUnavailableError` with code `SANDBOX_UNAVAILABLE` when no usable backend exists. Consumers may also classify a failure while spawning or observing the returned argv; that attribution belongs to the consumer contract. Silent unconfined passthrough is never legal for a confined policy.
|
|
158
|
+
|
|
159
|
+
Provider selection, probing, caching, and backend-specific enforcement reports belong to the [local provider](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/sandbox/sandbox-local/README.md).
|
|
160
|
+
|
|
161
|
+
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
162
|
+
|
|
163
|
+
<a id="cordis-surface"></a>
|
|
164
|
+
|
|
165
|
+
## Cordis API
|
|
166
|
+
|
|
167
|
+
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
|
168
|
+
|
|
169
|
+
<a id="ctxsandbox--sandboxprovider-abstract-seam"></a>
|
|
170
|
+
|
|
171
|
+
### `ctx.sandbox` — `SandboxProvider` (abstract seam)
|
|
172
|
+
|
|
173
|
+
Abstract process-sandbox service. confine must return enforcing argv or fail closed at wrap or runner-execution time; silent unconfined passthrough is forbidden. Functional probes arbitrate multi-runner chains and may be skipped for a sole candidate, whose own refusal remains the fail-closed end.
|
|
174
|
+
|
|
175
|
+
```ts cordis-catalog
|
|
176
|
+
/**
|
|
177
|
+
* Wrap `argv` so it executes confined under `policy` on this host; the
|
|
178
|
+
* caller spawns the returned argv in place of its own.
|
|
179
|
+
* @param argv - the exact argv the caller is about to spawn (program plus
|
|
180
|
+
* arguments), NOT a shell string — a shell-shaped consumer passes
|
|
181
|
+
* `['bash', '-c', command]`.
|
|
182
|
+
* @param policy - the file-effect policy this execution runs under,
|
|
183
|
+
* carried per call (see {@link SandboxPolicy}).
|
|
184
|
+
* @returns the argv to spawn instead, plus the enforcement completeness
|
|
185
|
+
* the selected backend achieves for it.
|
|
186
|
+
*/
|
|
187
|
+
abstract confine(argv: readonly string[], policy: SandboxPolicy): ConfinedArgv
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Source: [`packages/sandbox/sandbox/src/index.ts:158`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/sandbox/sandbox/src/index.ts)
|
|
191
|
+
|
|
192
|
+
<a id="ctxsandboxpolicy--sandboxpolicyservice"></a>
|
|
193
|
+
|
|
194
|
+
### `ctx.sandboxPolicy` — `SandboxPolicyService`
|
|
195
|
+
|
|
196
|
+
The sandbox-policy service (`ctx.sandboxPolicy`). Owns the deployment default mode, fallback workspace root, and current request-time policy section. Tool layers call resolve for each execution so a session's mode log and immutable cwd travel together to every enforcing capability.
|
|
197
|
+
|
|
198
|
+
```ts cordis-catalog
|
|
199
|
+
/**
|
|
200
|
+
* Resolve the complete policy for one capability call. An approved explicit
|
|
201
|
+
* mode outranks the session's last `sandbox/mode` event, which outranks the
|
|
202
|
+
* deployment default. A session cwd is its workspace-write boundary; the
|
|
203
|
+
* configured root is the fallback for agentless calls and sessions without a
|
|
204
|
+
* cwd.
|
|
205
|
+
* @param request - optional session and approved mode override.
|
|
206
|
+
* @returns the fully resolved per-call mode and absolute workspace root.
|
|
207
|
+
*/
|
|
208
|
+
resolve(request: SandboxPolicyRequest = {}): SandboxExecutionPolicy
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Read the session override without applying the deployment default.
|
|
212
|
+
* @param session - session whose log supplies the override.
|
|
213
|
+
* @returns the last logged mode, or `undefined` without one.
|
|
214
|
+
*/
|
|
215
|
+
overrideOf(session: Session): SandboxMode | undefined
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Types: [Session](./session.md)
|
|
219
|
+
|
|
220
|
+
Source: [`packages/sandbox/sandbox-policy/src/index.ts:91`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/sandbox/sandbox-policy/src/index.ts)
|
|
221
|
+
<!-- END GENERATED cordis-surface -->
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
editSource: "docs/subsystems/schedule.md"
|
|
3
|
+
outline: [2,3]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Session-local Schedule
|
|
7
|
+
|
|
8
|
+
Schedule owns durable reminders that return to the original live Session as ordinary later conversation turns. The [durable Schedule Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-08-05-durable-web-schedule.md) owns the persistence and lifecycle decisions, [conversational delivery](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/simplification/2026-08-09-conversational-schedule-delivery.md) owns the no-receipt boundary, the [explicit time-zone boundary](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/simplification/2026-08-09-explicit-schedule-time-zone.md) owns browser-local interpretation, and [bounded fixed-rate Schedule](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/simplification/2026-08-09-bounded-fixed-rate-schedule.md) owns recurrence. This page records the durable and model-facing shapes from [`packages/schedule/schedule/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/schedule/schedule/src/types.ts); the [package README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/schedule/schedule/README.md) owns composition, tool behavior, and the exact reminder framing.
|
|
9
|
+
|
|
10
|
+
## Durable records
|
|
11
|
+
|
|
12
|
+
`ScheduleId` is a [branded id](./core.md#branded-ids), unique and never reused within one Session. Version 1 supports a positive safe-integer `after_seconds` delay, an explicit absolute `at` target, or a safe-integer `every_seconds` interval of at least five minutes. Creation canonicalizes every first target into a four-digit-year RFC 3339 UTC `scheduledAt`; an `after` record retains its submitted delay, an `at` record stores only the resulting instant, and an `every` record retains its fixed interval and next target.
|
|
13
|
+
|
|
14
|
+
```ts type-equiv
|
|
15
|
+
/** Durable one-shot reminder created from a positive delay. */
|
|
16
|
+
interface AfterScheduleRecord {
|
|
17
|
+
/** Session-local stable identity. */
|
|
18
|
+
readonly id: ScheduleId
|
|
19
|
+
/** Rule discriminator for a delayed one-shot reminder. */
|
|
20
|
+
readonly kind: 'after'
|
|
21
|
+
/** Trimmed reminder content supplied at creation. */
|
|
22
|
+
readonly prompt: string
|
|
23
|
+
/** Positive safe-integer delay accepted at creation. */
|
|
24
|
+
readonly afterSeconds: number
|
|
25
|
+
/** Four-digit-year RFC 3339 UTC target. */
|
|
26
|
+
readonly scheduledAt: string
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```ts type-equiv
|
|
31
|
+
/** Durable one-shot reminder created from an absolute instant. */
|
|
32
|
+
interface AtScheduleRecord {
|
|
33
|
+
/** Session-local stable identity. */
|
|
34
|
+
readonly id: ScheduleId
|
|
35
|
+
/** Rule discriminator for an absolute one-shot reminder. */
|
|
36
|
+
readonly kind: 'at'
|
|
37
|
+
/** Trimmed reminder content supplied at creation. */
|
|
38
|
+
readonly prompt: string
|
|
39
|
+
/** Four-digit-year RFC 3339 UTC target. */
|
|
40
|
+
readonly scheduledAt: string
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```ts type-equiv
|
|
45
|
+
/** Durable fixed-rate reminder whose next target remains creation-anchor-aligned. */
|
|
46
|
+
interface EveryScheduleRecord {
|
|
47
|
+
/** Session-local stable identity. */
|
|
48
|
+
readonly id: ScheduleId
|
|
49
|
+
/** Rule discriminator for a fixed-rate recurring reminder. */
|
|
50
|
+
readonly kind: 'every'
|
|
51
|
+
/** Trimmed reminder content supplied at creation. */
|
|
52
|
+
readonly prompt: string
|
|
53
|
+
/** Fixed safe-integer interval, never below five minutes. */
|
|
54
|
+
readonly everySeconds: number
|
|
55
|
+
/** Earliest anchor-aligned occurrence not yet dispatched. */
|
|
56
|
+
readonly scheduledAt: string
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```ts type-equiv
|
|
61
|
+
/** One-shot record variants that terminate on an id-only dispatch. */
|
|
62
|
+
type OneShotScheduleRecord = AfterScheduleRecord | AtScheduleRecord
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```ts type-equiv
|
|
66
|
+
/** The v1 durable reminder record union. */
|
|
67
|
+
type ScheduleRecord = OneShotScheduleRecord | EveryScheduleRecord
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Absolute-time input
|
|
71
|
+
|
|
72
|
+
The `at` selector is either a strict offset-bearing RFC 3339 string or an exact local-calendar object. The local form keeps its interpretation explicit at the tool boundary:
|
|
73
|
+
|
|
74
|
+
```ts type-equiv
|
|
75
|
+
/** Structured local-calendar input accepted by `schedule_create`. */
|
|
76
|
+
interface LocalAtInput {
|
|
77
|
+
/** Four-digit ISO calendar date. */
|
|
78
|
+
readonly date: string
|
|
79
|
+
/** Local wall-clock time with optional one-to-three digit milliseconds. */
|
|
80
|
+
readonly time: string
|
|
81
|
+
/** Explicit UTC or IANA Area/Location zone. */
|
|
82
|
+
readonly time_zone: string
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```ts type-equiv
|
|
87
|
+
/** Absolute selector accepted by `schedule_create`. */
|
|
88
|
+
type AtInput = string | LocalAtInput
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The official Web overlay samples the browser's IANA zone for every prompt. Time-context tells the model to interpret otherwise-unqualified natural-language dates and times in that request-local zone when the open turn has one unambiguous browser zone; mixed or missing provenance tells the model to ask. That guidance is not a durable Session default: the model must still pass an offset in the string form or `time_zone` in the local form, and Schedule never reads browser, Session, process, or model context.
|
|
92
|
+
|
|
93
|
+
Schedule rejects invalid offsets and zones, offset-free strings, non-future targets, and local times inside daylight-saving gaps. A daylight-saving overlap chooses its first, earlier instant. Successful creation stores only canonical UTC `scheduledAt`, so replay never depends on ambient time-zone state.
|
|
94
|
+
|
|
95
|
+
## Fixed-rate input and catch-up
|
|
96
|
+
|
|
97
|
+
`every_seconds` is a per-record interval of at least 300 seconds, anchored to creation time. It is fixed-rate recurrence only: the protocol has no calendar or Cron expression, recurrence time zone, shared cooldown, or cross-record admission gate.
|
|
98
|
+
|
|
99
|
+
When a Session was cold or busy across several targets, one Every record contributes only its latest due occurrence. The dispatch advances it directly to the first creation-anchor-aligned target after the dispatch decision time, without enumerating, persisting, or replaying missed intervals. If that next target cannot fit in a four-digit UTC year, the final dispatch terminates the record.
|
|
100
|
+
|
|
101
|
+
When multiple distinct Every records are overdue and no one-shot is due, each contributes one occurrence to the same follow-up batch in target and creation order. Every record keeps independent state, while all dispatches in that admitted batch use the same decision time. Batching bounds model turns; the five-minute minimum bounds each record's timer frequency.
|
|
102
|
+
|
|
103
|
+
## Durable changes and replay
|
|
104
|
+
|
|
105
|
+
The version-1 `schedule/change` Session event is the only durable Schedule authority. Create stores the complete record, and delete is a terminal id-only transition. A one-shot dispatch is also terminal and id-only. An Every dispatch carries the wall-clock decision time used to select its latest due occurrence and normally advances the active record instead of terminating it. Dispatch means the follow-up was synchronously queued, not that a model answer succeeded or the user read it.
|
|
106
|
+
|
|
107
|
+
```ts type-equiv
|
|
108
|
+
/** Creates one durable reminder record. */
|
|
109
|
+
interface ScheduleCreateChange {
|
|
110
|
+
readonly version: 1
|
|
111
|
+
readonly operation: 'create'
|
|
112
|
+
readonly schedule: ScheduleRecord
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```ts type-equiv
|
|
117
|
+
/** Deletes one currently active reminder. */
|
|
118
|
+
interface ScheduleDeleteChange {
|
|
119
|
+
readonly version: 1
|
|
120
|
+
readonly operation: 'delete'
|
|
121
|
+
readonly id: ScheduleId
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```ts type-equiv
|
|
126
|
+
/** Records that one active one-shot reminder entered the durable dispatch history. */
|
|
127
|
+
interface OneShotScheduleDispatchChange {
|
|
128
|
+
readonly version: 1
|
|
129
|
+
readonly operation: 'dispatch'
|
|
130
|
+
readonly id: ScheduleId
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
```ts type-equiv
|
|
135
|
+
/** Records one fixed-rate decision and advances directly past missed occurrences. */
|
|
136
|
+
interface EveryScheduleDispatchChange {
|
|
137
|
+
readonly version: 1
|
|
138
|
+
readonly operation: 'dispatch'
|
|
139
|
+
readonly id: ScheduleId
|
|
140
|
+
/** Wall-clock decision time used to select the latest due occurrence. */
|
|
141
|
+
readonly acceptedAt: string
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```ts type-equiv
|
|
146
|
+
/** Durable dispatch shapes supported by the current rule set. */
|
|
147
|
+
type ScheduleDispatchChange = OneShotScheduleDispatchChange | EveryScheduleDispatchChange
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```ts type-equiv
|
|
151
|
+
/** Strict version-1 durable Schedule mutation union. */
|
|
152
|
+
type ScheduleChange = ScheduleCreateChange | ScheduleDeleteChange | ScheduleDispatchChange
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The strict decoder and fold reject unknown versions, extra fields, reused ids, mismatched one-shot or Every dispatch shapes, and delete or dispatch transitions against inactive records. A normal Session folds its complete event stream. A fork folds only events at or after `SessionHeader.seedLength`, so it retains history without adopting the parent Session's active reminders. The `schedule/change` declaration and source location are also indexed in the [persistence catalog](../persistence-catalog.md#schedulechange--log-only).
|
|
156
|
+
|
|
157
|
+
## Active views and management
|
|
158
|
+
|
|
159
|
+
Tool values combine the durable record with delivery state derived from the current wall clock. `session-local` means the original Session must be live: no external notification channel or cold-session scheduler exists.
|
|
160
|
+
|
|
161
|
+
```ts type-equiv
|
|
162
|
+
/** Current delivery timing derived from the durable record and wall clock. */
|
|
163
|
+
type ScheduleState = 'scheduled' | 'overdue'
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```ts type-equiv
|
|
167
|
+
/** Fixed v1 delivery boundary: the original session must be live. */
|
|
168
|
+
type ScheduleDeliveryMode = 'session-local'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```ts type-equiv
|
|
172
|
+
/** Complete model-facing view of one active reminder. */
|
|
173
|
+
type ScheduleView = ScheduleRecord & {
|
|
174
|
+
/** Whether the target remains in the future. */
|
|
175
|
+
readonly state: ScheduleState
|
|
176
|
+
/** Reminder delivery never leaves the owning session. */
|
|
177
|
+
readonly deliveryMode: ScheduleDeliveryMode
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The generated [tool catalog](../tool-catalog.md#deepseek-aidsh-schedule) owns the argument and result schemas for `schedule_create`, `schedule_list`, and `schedule_delete`. Management calls serialize with due work in one Agent-scoped queue. Every read or decision first waits for the shared Session persistence barrier; create and an actual delete wait again after appending. A barrier failure reports `persistence_uncertain` instead of guessing whether an eager write committed. The other stable error codes are `invalid_prompt`, `invalid_selector`, `invalid_rule`, `invalid_time_zone`, `not_future`, `time_out_of_range`, `frequency_too_high`, `corrupt_schedule_log`, and `internal_error`.
|
|
182
|
+
|
|
183
|
+
## Live delivery
|
|
184
|
+
|
|
185
|
+
The process-local owner derives its earliest timer from the durable fold and rereads the wall clock after every bounded wait. Cold Sessions do no work; reopening one reconstructs timers and makes past targets overdue. Due one-shots take priority and enter one later turn at a time. When no one-shot is due, all overdue Every records form the single batch described above.
|
|
186
|
+
|
|
187
|
+
Due work waits for the Agent to become fully idle and claims the maintenance phase before it refolds state, samples the decision, queues one `followup()`, and appends the corresponding dispatch changes. It never calls `steer()` and never interrupts a current turn.
|
|
188
|
+
|
|
189
|
+
The admitted one-shot or fixed-rate batch starts one normal later turn and appears only through the ordinary conversation transcript; Schedule has no independent durable Web receipt or browser renderer. If framing or synchronous queue admission fails, no dispatch is recorded and the reminder stays active. The narrow crash interval after admission but before durable dispatch can repeat reminder content after recovery, so the boundary is best-effort at-least-once rather than exactly-once delivery.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
editSource: "docs/subsystems/scope.md"
|
|
3
|
+
outline: [2,3]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Scoped Registration
|
|
7
|
+
|
|
8
|
+
The [scope package](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/scope) supplies the identity, carrier, and scoped-layer vocabulary that makes one registration context mean both per-agent visibility and shared lifetime ownership. It is a library primitive rather than a Cordis service; the [agent-scope runtime-design Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.md#scope-routing-one-opaque-key-selects-one-layer) owns the lifecycle rationale, the [shared-storage Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-12-scoped-layers-store.md) owns the registry-layer decision, and the package [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/scope/README.md) owns the callable API and filtering semantics.
|
|
9
|
+
|
|
10
|
+
Sources: [`packages/core/scope/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/scope/src/index.ts) and [`packages/core/scope/src/store.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/scope/src/store.ts).
|
|
11
|
+
|
|
12
|
+
## Identity and dispatch carrier
|
|
13
|
+
|
|
14
|
+
`ScopeKey` is an opaque object identity. The shipped loop uses the live `Agent` object as its own key, but the primitive never inspects the object.
|
|
15
|
+
|
|
16
|
+
```ts type-equiv
|
|
17
|
+
/** An opaque, identity-compared scope key. */
|
|
18
|
+
type ScopeKey = object
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`Scoped<T>` is the compile-time brand on the opaque routing receiver returned by `scopeTarget(base, key)`. Scope-filtered event declarations require this carrier as their `this` type, while the real event subject remains an explicit argument.
|
|
22
|
+
|
|
23
|
+
```ts type-equiv
|
|
24
|
+
/**
|
|
25
|
+
* A routing-only event receiver built by {@link scopeTarget}. The type
|
|
26
|
+
* parameter records the subject type for dispatch checking; the carrier does
|
|
27
|
+
* not expose the subject's properties. Event payloads carry the real subject.
|
|
28
|
+
*/
|
|
29
|
+
type Scoped<T extends object> = object & { readonly [ScopedBrand]: T }
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Owned registration context
|
|
33
|
+
|
|
34
|
+
`Scope` pairs the tagged registration context with two teardown paths. `rawDispose` preserves the exact Cordis disposer identity needed by an ordered composite effect; `dispose()` is the public shared quiescence boundary for direct and racing callers.
|
|
35
|
+
|
|
36
|
+
```ts type-equiv
|
|
37
|
+
/** A minted registration scope and its quiescent disposal boundaries. */
|
|
38
|
+
interface Scope {
|
|
39
|
+
/** Context through which scope-owned registrations are made. */
|
|
40
|
+
ctx: Context
|
|
41
|
+
/** Exact Cordis disposer, used when nesting this scope in an ordered composite effect. */
|
|
42
|
+
rawDispose: () => Promise<void> | void
|
|
43
|
+
/** Dispose every scope-owned registration; racing calls await the same completion. */
|
|
44
|
+
dispose(): Promise<void>
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Scoped registry layer
|
|
49
|
+
|
|
50
|
+
`ScopeLayer` represents one registry's complete contribution at the global or exact-scope level. A concrete layer may aggregate multiple named and anonymous tables; whole-layer emptiness lets `ScopedLayers` reclaim scoped state without discarding a sibling table.
|
|
51
|
+
|
|
52
|
+
```ts type-equiv
|
|
53
|
+
/** One scope's aggregate contribution to a registry. */
|
|
54
|
+
interface ScopeLayer {
|
|
55
|
+
/** Whether every table in this layer is empty. */
|
|
56
|
+
isEmpty(): boolean
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`ScopedLayers<L>` owns the eager global layer and lazily created exact-scope layers. Reads do not create layers: `peek(undefined)` means no overlay, while `merge()` materializes insertion-ordered global named entries followed by scoped shadows. Registrations use one context for both visibility and Cordis effect ownership, collect one synchronous undo before optional notification, return Cordis's exact disposer, and reclaim a scoped layer only when its complete `ScopeLayer` is empty.
|
|
61
|
+
|
|
62
|
+
`NamedEntries<V>` supplies insertion-ordered lookup and live iteration with caller-owned duplicate errors. `AnonymousEntries<V>` gives every append a unique identity so equal values remain independent. Iteration stays live within one nonempty table generation; draining the table detaches existing iterators from later insertions. Both return idempotent exact-entry undos; the shared `EntryValues` implementation interface is not public.
|