fix(boot): limit required IDs to application endpoints
This commit is contained in:
1 parent
f4a7dd6077
commit
7fd41b833b
8 files changed
+11
-15
No files matched your search
+2
-2
@@ -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 .agents/notes/implemented/architecture/2026-09-09-consumer-owned-startup-strictness.md
|
||||
2026-09-09-consumer-owned-startup-strictness.md: eab57329bc33c6a341d1073275deb4fd2355f041
|
||||
2026-09-09-consumer-owned-startup-strictness.zh.md: 687017533d114cd1e13205b50373fc415eb99c2a
|
||||
2026-09-09-consumer-owned-startup-strictness.md: dd93e3867452e4456e2d7e1853e01aff66deb881
|
||||
2026-09-09-consumer-owned-startup-strictness.zh.md: dfb84c803ead167807897fe18d39f19d00eecac4
|
||||
+1
-1
@@ -12,7 +12,7 @@ Best-effort Loader reconciliation preserves usable plugins, but applications sti
|
||||
|
||||
DSH owns startup strictness outside vendored Cordis. App-boot audits the settled initial tree against one global list of stable entry ids. A listed entry that is present, enabled, and not active rejects startup and disposes the application. A listed id that is absent or disabled has no effect. The bootstrap Include is required by entry identity because a missing or invalid root configuration prevents application assembly. Other inactive entries produce one warning and leave successful siblings running.
|
||||
|
||||
The required ids are `agent-loop`, `webserver`, `modules`, `connection`, `headless-runner`, `acp`, and `sdk-jsonrpc-server`. They represent shared Agent execution and the endpoints of the shipped Web, headless, ACP, and SDK applications. Their injected providers do not need separate list entries: a missing provider leaves the listed endpoint pending or failed.
|
||||
The required ids are `agent-loop`, `webserver`, `headless-runner`, `acp`, and `sdk-jsonrpc-server`. They represent shared Agent execution and the endpoints of the shipped Web, headless, ACP, and SDK applications. Their injected providers do not need separate list entries: a missing provider leaves the listed endpoint pending or failed.
|
||||
|
||||
The audit runs only during initial application boot. Later config HMR remains best effort and keeps the failed candidate visible for repair.
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ Best-effort Loader reconcile 会保留可用 plugin,但应用仍需一组最
|
||||
|
||||
DSH 在 vendored Cordis 之外持有启动严格语义。App-boot 用一份全局稳定 entry id list 审计已结算的初始 tree。List 中存在、启用且未 active 的 entry 会使启动 reject,并拆卸应用。List 中缺失或禁用的 id 不产生影响。Bootstrap Include 按 entry 身份被视为 required,因为根配置缺失或无效会阻止应用组装。其他 inactive entry 输出一次 warning,并让成功 sibling 继续运行。
|
||||
|
||||
Required id 为 `agent-loop`、`webserver`、`modules`、`connection`、`headless-runner`、`acp` 和 `sdk-jsonrpc-server`。它们分别代表共享 Agent 执行,以及随附 Web、headless、ACP 和 SDK 应用的 endpoint。其 injected provider 不需要单列:provider 缺失会让已列出的 endpoint 保持 pending 或失败。
|
||||
Required id 为 `agent-loop`、`webserver`、`headless-runner`、`acp` 和 `sdk-jsonrpc-server`。它们分别代表共享 Agent 执行,以及随附 Web、headless、ACP 和 SDK 应用的 endpoint。其 injected provider 不需要单列:provider 缺失会让已列出的 endpoint 保持 pending 或失败。
|
||||
|
||||
该审计只在应用首次启动时运行。之后的 config HMR 仍采用 best effort,并保留 failed candidate 供后续修复。
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/boot/app-boot/README.md
|
||||
README.md: 28d6cfd622947378367da59b1e6a897c8f9f2664
|
||||
README.zh.md: 593e3105bf50a3a04cf70a0df97e8f347081701b
|
||||
README.md: 55689d496dcd1610ba45c0fc6140296968652410
|
||||
README.zh.md: 7d320a045d16571576340e5238a1372f4ec6f4ba
|
||||
@@ -40,7 +40,7 @@ installFailLoud('dsh')
|
||||
const ctx = await boot('dsh', resolveConfigPath(argv[2], process.env.DSH_SNAPSHOT))
|
||||
```
|
||||
|
||||
With that entry point, startup keeps every plugin that can activate. An enabled failed plugin produces a labelled warning. A failed required entry makes startup dispose the whole app and exit nonzero; required ids absent from a profile and disabled required entries do not affect startup. The global required list covers shared Agent execution and each application's endpoint: `agent-loop`, `webserver`, `modules`, `connection`, `headless-runner`, `acp`, and `sdk-jsonrpc-server`.
|
||||
With that entry point, startup keeps every plugin that can activate. An enabled failed plugin produces a labelled warning. A failed required entry makes startup dispose the whole app and exit nonzero; required ids absent from a profile and disabled required entries do not affect startup. The global required list covers shared Agent execution and each application's endpoint: `agent-loop`, `webserver`, `headless-runner`, `acp`, and `sdk-jsonrpc-server`.
|
||||
|
||||
<a id="profiles"></a>
|
||||
### Profiles
|
||||
|
||||
@@ -40,7 +40,7 @@ installFailLoud('dsh')
|
||||
const ctx = await boot('dsh', resolveConfigPath(argv[2], process.env.DSH_SNAPSHOT))
|
||||
```
|
||||
|
||||
有了这个入口,启动会保留所有能够激活的插件。启用但失败的插件会产生带标签的警告。required entry 失败时,启动会拆卸整个应用并以非零码退出;profile 中不存在的 required id 和已禁用的 required entry 不影响启动。全局 required list 覆盖共享 Agent 执行与各应用的 endpoint:`agent-loop`、`webserver`、`modules`、`connection`、`headless-runner`、`acp` 和 `sdk-jsonrpc-server`。
|
||||
有了这个入口,启动会保留所有能够激活的插件。启用但失败的插件会产生带标签的警告。required entry 失败时,启动会拆卸整个应用并以非零码退出;profile 中不存在的 required id 和已禁用的 required entry 不影响启动。全局 required list 覆盖共享 Agent 执行与各应用的 endpoint:`agent-loop`、`webserver`、`headless-runner`、`acp` 和 `sdk-jsonrpc-server`。
|
||||
|
||||
<a id="profiles"></a>
|
||||
### Profile
|
||||
|
||||
@@ -703,8 +703,6 @@ const FIBER_FAILED = 3 as FiberState.FAILED
|
||||
export const REQUIRED_STARTUP_ENTRY_IDS: readonly string[] = Object.freeze([
|
||||
'agent-loop',
|
||||
'webserver',
|
||||
'modules',
|
||||
'connection',
|
||||
'headless-runner',
|
||||
'acp',
|
||||
'sdk-jsonrpc-server',
|
||||
|
||||
@@ -537,8 +537,6 @@ describe('auditStartupEntries', () => {
|
||||
expect(REQUIRED_STARTUP_ENTRY_IDS).toEqual([
|
||||
'agent-loop',
|
||||
'webserver',
|
||||
'modules',
|
||||
'connection',
|
||||
'headless-runner',
|
||||
'acp',
|
||||
'sdk-jsonrpc-server',
|
||||
@@ -667,10 +665,10 @@ describe('auditStartupEntries', () => {
|
||||
|
||||
it('rejects a required entry pending on an injected service', async () => {
|
||||
await expect(auditStartupEntries(ctxWith([{
|
||||
fiber: fiber(0, undefined, { webRuntime: {} }),
|
||||
options: { id: 'connection', name: '@deepseek-ai/dsh-client-connection' },
|
||||
fiber: fiber(0, undefined, { headlessStartup: {} }),
|
||||
options: { id: 'headless-runner', name: '@deepseek-ai/dsh-headless' },
|
||||
}]), NAME, vi.fn())).rejects.toThrow(
|
||||
'connection (@deepseek-ai/dsh-client-connection): pending (waiting for service: webRuntime)',
|
||||
'headless-runner (@deepseek-ai/dsh-headless): pending (waiting for service: headlessStartup)',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user