Merge origin/master into codex/code-mode-complete-result-card

This commit is contained in:
Tianyi Cui
2026-07-23 17:59:58 +08:00
273 changed files with 10384 additions and 4555 deletions

View File

@@ -1,11 +1,11 @@
{
"AGENTS.md": 1600,
"AGENTS.md": 1680,
"docs/AGENTS.md": 1150,
"docs/architecture.md": 1800,
"docs/cordis-primer.md": 600,
"docs/defensive-patterns.md": 550,
"docs/testing.md": 960,
"docs/testing.md": 1020,
"examples/AGENTS.md": 310,
"packages/AGENTS.md": 650,
"packages/AGENTS.md": 660,
"packages/README.md": 760
}

View File

@@ -55,15 +55,20 @@ const configHost: ts.ParseConfigFileHost = {
},
}
/** Load root settings and redirect workspace aliases to declarations from the coordinated build. */
/**
* Load host-aggregate settings and redirect workspace aliases to declarations
* from the coordinated build. Doc fragments speak the host vocabulary; the host
* aggregate (never the root solution — it has no compilerOptions) carries the
* workspace paths via tsconfig.base.json.
*/
function builtTypeCompilerOptions(): ts.CompilerOptions {
const configPath = join(root, 'tsconfig.json')
const configPath = join(root, 'tsconfig.host.json')
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, configHost)
if (!parsed) throw new Error(`doc-typecheck: cannot parse ${configPath}`)
if (parsed.errors.length > 0) {
throw new Error(parsed.errors.map(error => ts.flattenDiagnosticMessageText(error.messageText, '\n')).join('\n'))
}
if (parsed.options.paths === undefined) throw new Error('doc-typecheck: root tsconfig has no workspace paths')
if (parsed.options.paths === undefined) throw new Error('doc-typecheck: host tsconfig has no workspace paths')
const paths = Object.fromEntries(Object.entries(parsed.options.paths).map(([specifier, candidates]) => [
specifier,
candidates.map(builtDeclarationPath),
@@ -125,9 +130,14 @@ function formatDiagnostics(diagnostics: readonly ts.Diagnostic[], blocks: Block[
return remapBlockPaths(formatted, blocks)
}
/** Reuse the repo typecheck graph references from a temp project one directory below root. */
/**
* Reuse the host-aggregate references from a temp project one directory below
* root. Doc fragments speak the host vocabulary, so the standalone project
* seeds tsconfig.host.json (never the root solution: flattening host+client
* into one program collides the cordis Context merges).
*/
function workspaceReferences(): { path: string }[] {
const file = join(root, 'tsconfig.json')
const file = join(root, 'tsconfig.host.json')
// Parse with TypeScript's own JSONC reader: a regex comment stripper corrupts the `/*/` path
// candidate in the workspace wildcard.
const result = ts.readConfigFile(file, path => readFileSync(path, 'utf8'))
@@ -144,7 +154,7 @@ function workspaceReferences(): { path: string }[] {
/** The standalone temp project used when no coordinated build owns declaration freshness. */
function tempTsconfig(): string {
return JSON.stringify({
extends: '../tsconfig.json',
extends: '../tsconfig.host.json',
compilerOptions: {
noUnusedLocals: false,
noUnusedParameters: false,

View File

@@ -198,6 +198,8 @@ const TYPE_LINK_EXEMPTIONS: Readonly<Record<string, string>> = {
LocaleDict: 'service-local dictionary shape is owned by packages/client/i18n/src/index.ts',
ThemeTokens: 'service-local token dictionary is owned by packages/client/ui-theme/src/index.ts',
Translate: 'service-local bound translator is owned by packages/client/i18n/src/index.ts',
TuiOverlayRequest: 'service-local extension contract is owned by packages/ui/tui/README.md',
TuiOverlaySession: 'service-local extension contract is owned by packages/ui/tui/README.md',
InvariantRegistration: 'service-local lifecycle handle is owned by packages/support/invariants/README.md',
PresetOption: 'deployment menu metadata is owned by packages/ui/permission/README.md',
PresetSpec: 'deployment preset composition is owned by packages/ui/permission/README.md',

View File

@@ -197,6 +197,13 @@ const SERVICE_ROLES: ServiceRole[] = [
consumers: ['tui', 'acp'],
note: 'Plugins register direct human commands; TUI and ACP consume the same effective per-agent catalog without sending invocations to the model.',
},
{
key: 'tui',
pkg: 'tui',
title: 'Mounted-terminal interaction service',
mode: 'bundle',
note: 'One TUI front door provides a FIFO overlay host; injected plugins receive caller-fiber ownership without access to pi-tui or terminal lifecycle state.',
},
{
key: 'skills',
pkg: 'skill',

View File

@@ -370,7 +370,7 @@ function quote(value: string): string {
/**
* Render the generated scoped-event resolver module for one repository root.
* @param projectRoot - repository root carrying tsconfig.json.
* @param projectRoot - repository root carrying tsconfig.host.json.
* @returns complete generated TypeScript source.
*/
export function renderScopedEvents(projectRoot: string = root): string {

View File

@@ -228,7 +228,10 @@ function ciPrimaryGates(): Gate[] {
...docSyncLeafGates(),
pnpmScript('module-graph', 'verify-module-graph', { label: 'module graph' }),
pnpmScript('knip', 'knip'),
pnpmScript('build', 'build'),
// typecheck and build now drive the same root solution graph; without the
// dependency two concurrent `tsc -b` runs race the same tsbuildinfo files.
// The tsc step is an incremental no-op after typecheck.
pnpmScript('build', 'build', { needs: ['typecheck'] }),
pnpmScript('publint', 'publint', { needs: ['build'] }),
pnpmScript('node-next-types', 'verify-node-next-types', {
label: 'node-next types',

View File

@@ -22,9 +22,13 @@ const configHost: ts.ParseConfigFileHost = {
},
}
/** Parse a root tsconfig and flatten all referenced projects into one semantic graph. */
/**
* Parse the host aggregate tsconfig and flatten all referenced projects into one
* semantic graph. Never seed the root solution: flattening host+client into one
* program collides the cordis Context merges.
*/
function loadProjectGraph(projectRoot: string): ProjectGraph {
const rootConfigPath = resolve(projectRoot, 'tsconfig.json')
const rootConfigPath = resolve(projectRoot, 'tsconfig.host.json')
const rootConfig = parseConfig(rootConfigPath)
const rootNames = new Set<string>()
const visited = new Set<string>()

View File

@@ -152,12 +152,13 @@ function localPackageDirectories(): Map<string, string> {
}
function rootProjectReferences(): Set<string> {
// Typecheck runs two sibling aggregates (root = host program,
// tsconfig.client.json = client program; the two sides merge cordis Context
// under the same keys, so one program cannot see both). Seed both and follow
// any nested aggregate references to collect the covered leaf project set.
// The root solution references the host and client aggregates (the two
// sides merge cordis Context under the same keys, so one program cannot see
// both — but this BFS only collects reference paths, it never forms a
// program). Seed the solution and follow nested aggregate references to
// collect the covered leaf project set.
const collected = new Set<string>()
const queue = [resolve(root, 'tsconfig.json'), resolve(root, 'tsconfig.client.json')]
const queue = [resolve(root, 'tsconfig.json')]
const seen = new Set<string>()
for (let file = queue.pop(); file !== undefined; file = queue.pop()) {
if (seen.has(file)) continue