Merge branch 'merge/1829-master' into merge/1990-1829

# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
This commit is contained in:
Huanqi Cao
2026-08-10 12:35:32 +08:00
331 changed files with 16605 additions and 558 deletions

View File

@@ -1,11 +1,11 @@
{
"AGENTS.md": 1782,
"AGENTS.md": 1900,
"docs/AGENTS.md": 1320,
"docs/architecture.md": 2174,
"docs/architecture.md": 2400,
"docs/cordis-primer.md": 600,
"docs/defensive-patterns.md": 550,
"docs/testing.md": 1150,
"examples/AGENTS.md": 310,
"packages/AGENTS.md": 675,
"packages/README.md": 936
"packages/README.md": 980
}

View File

@@ -45,6 +45,7 @@ export { REGION_BEGIN, REGION_END }
export const SERVICE_PAGE: Record<string, string> = {
agentLoop: 'core.md',
agentDefaultModel: 'core.md',
agentPresets: 'core.md',
agents: 'core.md',
approval: 'approval.md',
bash: 'bash.md',
@@ -346,6 +347,7 @@ export const LINK_MAP: Readonly<Record<string, string>> = {
SkillProvider: 'skills.md',
SkillProviderObservation: 'skills.md',
SkillRegistration: 'skills.md',
SkillViewOptions: 'skills.md',
SkillSummary: 'skills.md',
SaveTextSpill: 'spill.md',
SpillRef: 'spill.md',
@@ -388,6 +390,7 @@ export const LINK_MAP: Readonly<Record<string, string>> = {
ToolExecutionResult: 'tools.md',
ToolExecutionToken: 'tools.md',
ToolGuard: 'tools.md',
ToolPresentationMode: 'tools.md',
ToolRegistry: 'tools.md',
ToolRestriction: 'tools.md',
ToolSchema: 'tools.md',
@@ -462,6 +465,9 @@ export const TYPE_LINK_EXEMPTIONS: Readonly<Record<string, string>> = {
InsertReferenceRequest: 'event-local request contract is owned by packages/client/ui-slash/src/types.ts',
ConsumeTokenRequest: 'event-local request contract is owned by packages/client/ui-slash/src/types.ts',
InsertTextRequest: 'event-local request contract is owned by packages/client/ui-slash/src/types.ts',
AgentHandle: 'agent ownership handle is owned by packages/core/agent/README.md',
AgentPreset: 'discovered preset record is owned by packages/preset/agent-presets/README.md',
PresetMetadata: 'preset display text is owned by packages/preset/agent-presets/README.md',
BashEnvContributor: 'service-local extension type is owned by packages/bash/tool-bash/src/index.ts',
BashEnvVariableInfo: 'service-local metadata type is owned by packages/bash/tool-bash/src/index.ts',
CompactAgentContext: 'compaction service input is owned by packages/compact/compact/src/index.ts',

View File

@@ -267,6 +267,13 @@ const SERVICE_ROLES: ServiceRole[] = [
mode: 'core',
note: 'Folds logged plan/mode state, flushes user selections at turn boundaries, renders deployment-owned guidance, registers /plan, and keeps the plan-exit schema stable across transitions.',
},
{
key: 'agentPresets',
pkg: 'agent-presets',
title: 'Per-session agent composition',
mode: 'core',
note: 'Discovers preset directories over trusted and user-authored roots and mounts one preset cordis.yml under an agent scope during creation, rejecting a row that never activates or that publishes into the root service realm.',
},
{
key: 'commands',
pkg: 'commands',

View File

@@ -1060,6 +1060,11 @@
"symbol": "SkillLookupOptions",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/subsystems/skills.md",
"symbol": "SkillViewOptions",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/subsystems/skills.md",
"symbol": "SkillProviderObservation",

View File

@@ -78,6 +78,7 @@ for (const file of files) {
errors.push(...validateExampleResolution())
errors.push(...validateAppResolution())
errors.push(...validateSourcePlaneResolution())
errors.push(...validatePresetPlaneSeparation())
if (errors.length > 0) {
console.error('verify-cordis-config: invalid Loader metadata or plugin package resolution:')
@@ -87,6 +88,76 @@ if (errors.length > 0) {
console.log(`verify-cordis-config: ${files.length} config files passed.`)
}
/**
* No shipped agent preset may repeat a row the host composition still runs.
*
* A preset contributes what ONE session adds to the host's registries. A row
* active on both planes is therefore mounted twice — once per process and once
* per session — and what that costs depends on what the row does: a provider
* behind an `isolate` realm shadows the host's for its own consumers, so a host
* contributor to that service reaches nobody; a row that registers into a host
* singleton registers once per live session, so the second one collides.
*
* Both have happened. `bash-env` in a preset realm left `DSH_WEB_URL` reaching
* no shell, and `tool-subagent-report` handed every child `report` once per live
* session until the second registration threw. Neither changes a tool catalog,
* so no catalog assertion can see them — and the shipped presets are near-copies
* of each other, so a fix applied to three of four is the normal failure.
* @returns one diagnostic per preset row that is also active on the host plane.
*/
function validatePresetPlaneSeparation(): string[] {
const problems: string[] = []
// The shipped Web surface is two bundle patch layers over an empty root.
const hostFile = 'packages/bundle/base/cordis.patch.yml'
const overlayFile = 'packages/bundle/web-app/cordis.patch.yml'
const hostRows = rowIds(hostFile)
const overlay = loadEntries(overlayFile)
const disabled = new Set<string>()
for (const entry of overlay) {
if (!isRecord(entry)) continue
if (entry.disabled === true && typeof entry.id === 'string') disabled.add(entry.id)
}
// The overlay's own inserts are host-plane too; its disables take them back out.
const active = new Set([...hostRows, ...rowIds(overlayFile)].filter(id => !disabled.has(id)))
for (const file of globSync('apps/cli/config/agent-presets/*/agent.cordis.yml', { cwd: root })) {
for (const id of rowIds(file)) {
if (!active.has(id)) continue
problems.push(
`${file}: row "${id}" is also active in the host composition; `
+ 'a row belongs to exactly one plane',
)
}
}
return problems
}
/** Every entry of one config file, or an empty list when it is not an entry array. */
function loadEntries(file: string): unknown[] {
const document: unknown = yaml.load(readFileSync(resolve(root, file), 'utf8'), { schema })
return isUnknownArray(document) ? document : []
}
/**
* Row ids declared anywhere in one config file, including inside group `config`
* lists — a preset nests most of its rows in `isolate` groups.
* @param file - repository-relative config path.
* @returns the declared ids.
*/
function rowIds(file: string): Set<string> {
const ids = new Set<string>()
const walk = (value: unknown): void => {
if (isUnknownArray(value)) {
for (const item of value) walk(item)
return
}
if (!isRecord(value)) return
if (typeof value.id === 'string' && typeof value.name === 'string') ids.add(value.id)
for (const child of Object.values(value)) walk(child)
}
walk(loadEntries(file))
return ids
}
function validateEntry(value: unknown, file: string, path: string): void {
if (!isRecord(value)) {
errors.push(`${file}${path}: entry must be an object`)

View File

@@ -47,8 +47,11 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
'packages/bash/bash-local': { kind: 'indirect', reason: 'The executor backend delegates model rendering to dsh-tool-bash.' },
'packages/bash/pwsh-local': { kind: 'indirect', reason: 'The executor backend delegates model rendering to dsh-tool-pwsh.' },
'packages/code-runtime/code-runtime': { kind: 'indirect', reason: 'The service interface delegates model rendering to Code Mode in dsh-tools.' },
'packages/core/agent-tool-mode': { kind: 'indirect', reason: 'The row only selects between the two projections dsh-tools owns; it registers no prompt, schema, or result of its own.' },
'packages/code-runtime/code-runtime-worker': { kind: 'indirect', reason: 'The worker backend delegates model rendering to Code Mode in dsh-tools.' },
'packages/client/ui-agent-preset': { kind: 'indirect', reason: 'Browser-side settings row; the preset it selects owns every model-facing effect.' },
'packages/core/agent-default-model': { kind: 'indirect', reason: 'The service supplies a ModelSelection; request assembly and adapters own the model-visible request.' },
'packages/preset/agent-presets': { kind: 'indirect', reason: 'The mount installs a preset\'s own plugins, which own every model-facing registration it makes visible.' },
'packages/typert/registry': { kind: 'none', reason: 'Runtime type registry; consumers (cordis_inspect, wire faces, gates) own any model-visible projection of registry contents.' },
'packages/typert/loader': { kind: 'none', reason: 'Loader integration only registers generated artifacts; consumers own any model-visible projection.' },
'packages/e2b/e2b': { kind: 'none', reason: 'The shared remote-runtime owner registers no model context; provider adapters and consumers own rendered effects.' },