Merge origin/master into feat/website-docs
Conflict resolution notes: - package.json/run-gates: both sides' new doc-sync gates kept (master's scoped-events/readme gates + this branch's website-api/website-yaml); js-yaml devDeps deduped (master added them independently). - pnpm-workspace/knip: website AND python/sdk-runtime entries kept. - doc-typecheck/verify-type-equiv: master's condensed headers kept, website glob retained in both scan scopes. - vendor/cordis/src/fiber.ts: master's lifecycle-hardening code taken; this branch's richer FiberState JSDoc reapplied on top. vendor/README.md logs both local modifications (hardening = 6, JSDoc enrichment = 7). - pnpm-lock: regenerated from master's side (pnpm install). Post-merge sync the gates forced (the system working as designed): - verify-website-yaml caught 4 stale plugin names from master's package reorg (dsh-stdio-agent -> dsh-stdio-demo, dsh-acp-agent -> dsh-acp-demo); 8 references fixed across guide/ and develop/. - gen-website-api picked up master's 6 new services automatically (ctx.approval/permission/sandbox/sessionQuery/skills/tasks -> 6 new pages + sidebar); api/index.md hub updated to list them. - AGENTS.md budget ceiling 1370 -> 1400: the website rows (layout line + two command lines) and master's own growth collided with the old ceiling; all three website rows are load-bearing (new top-level dir, new CI command).
This commit is contained in:
@@ -96,8 +96,7 @@ function pnpmScript(id: string, script: string, options: Partial<Gate> = {}): Ga
|
||||
return {
|
||||
id,
|
||||
label: options.label ?? script,
|
||||
command: pnpmBin(),
|
||||
args: ['run', script],
|
||||
...pnpmInvocation(['run', script]),
|
||||
...options,
|
||||
}
|
||||
}
|
||||
@@ -106,14 +105,18 @@ function pnpmExec(id: string, args: string[], options: Partial<Gate> = {}): Gate
|
||||
return {
|
||||
id,
|
||||
label: options.label ?? `pnpm exec ${args.join(' ')}`,
|
||||
command: pnpmBin(),
|
||||
args: ['exec', ...args],
|
||||
...pnpmInvocation(['exec', ...args]),
|
||||
...options,
|
||||
}
|
||||
}
|
||||
|
||||
function pnpmBin(): string {
|
||||
return process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm'
|
||||
function pnpmInvocation(args: string[]): Pick<Gate, 'command' | 'args'> {
|
||||
const entrypoint = process.env.npm_execpath
|
||||
if (entrypoint === undefined || entrypoint === '') {
|
||||
throw new Error('run-gates: npm_execpath is unavailable; invoke the runner through a pnpm package script.')
|
||||
}
|
||||
// Windows cannot spawn the pnpm.cmd shim directly; the JavaScript entrypoint keeps every host shell-free.
|
||||
return { command: process.execPath, args: [entrypoint, ...args] }
|
||||
}
|
||||
|
||||
function nodeOptions(...options: string[]): string {
|
||||
@@ -129,6 +132,7 @@ function gatesForMode(selected: Mode): Gate[] {
|
||||
case 'ci-lint':
|
||||
return [
|
||||
lintGate(),
|
||||
pnpmScript('duplication', 'duplication'),
|
||||
]
|
||||
case 'ci-coverage':
|
||||
return [
|
||||
@@ -143,10 +147,18 @@ function gatesForMode(selected: Mode): Gate[] {
|
||||
case 'node-compat':
|
||||
return [
|
||||
pnpmScript('typecheck', 'typecheck'),
|
||||
pnpmExec('source-worker-smoke', [
|
||||
'vitest',
|
||||
'run',
|
||||
'packages/workflow/workflow-workerthread/tests/source-worker.compat.spec.ts',
|
||||
], { label: 'source worker smoke' }),
|
||||
]
|
||||
case 'pre-push':
|
||||
return [
|
||||
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
|
||||
pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }),
|
||||
pnpmScript('test', 'test'),
|
||||
pnpmScript('duplication', 'duplication'),
|
||||
pnpmScript('snapshot', 'test:snapshot'),
|
||||
pnpmScript('build', 'build'),
|
||||
...hygieneLeafGates({ artifactNeeds: ['build'] }),
|
||||
@@ -158,9 +170,12 @@ function gatesForMode(selected: Mode): Gate[] {
|
||||
|
||||
function ciPrimaryGates(): Gate[] {
|
||||
return [
|
||||
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
|
||||
pnpmScript('constraints', 'constraints'),
|
||||
pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }),
|
||||
pnpmScript('typecheck', 'typecheck'),
|
||||
lintGate(),
|
||||
pnpmScript('duplication', 'duplication'),
|
||||
coverageGate(),
|
||||
pnpmScript('snapshot', 'test:snapshot'),
|
||||
demoSmokeGate({ needs: ['lint'] }),
|
||||
@@ -180,8 +195,10 @@ function ciPrimaryGates(): Gate[] {
|
||||
|
||||
function ciStaticGates(): Gate[] {
|
||||
return [
|
||||
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
|
||||
pnpmScript('constraints', 'constraints'),
|
||||
demoSmokeGate(),
|
||||
pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }),
|
||||
...staticDemoSmokeGates(),
|
||||
...docSyncLeafGates(),
|
||||
pnpmScript('module-graph', 'verify-module-graph', { label: 'module graph' }),
|
||||
pnpmScript('knip', 'knip'),
|
||||
@@ -189,6 +206,11 @@ function ciStaticGates(): Gate[] {
|
||||
]
|
||||
}
|
||||
|
||||
function staticDemoSmokeGates(): Gate[] {
|
||||
// Native Windows session persistence is outside the gates-only support scope.
|
||||
return process.platform === 'win32' ? [] : [demoSmokeGate()]
|
||||
}
|
||||
|
||||
function ciArtifactGates(): Gate[] {
|
||||
return [
|
||||
pnpmScript('build', 'build'),
|
||||
@@ -264,17 +286,21 @@ function docSyncLeafGates(): Gate[] {
|
||||
pnpmScript('config-catalog', 'verify-config-catalog', { label: 'config catalog' }),
|
||||
pnpmScript('persistence-catalog', 'verify-persistence-catalog', { label: 'persistence catalog' }),
|
||||
pnpmScript('doc-graphs', 'verify-doc-graphs', { label: 'doc graphs' }),
|
||||
pnpmScript('scoped-events', 'verify-scoped-events', { label: 'scoped events' }),
|
||||
pnpmScript('website-api', 'verify-website-api', { label: 'website api' }),
|
||||
pnpmScript('markdown-wrap', 'verify-md-wrap', { label: 'markdown wrap' }),
|
||||
pnpmScript('markdown-links', 'verify-md-links', { label: 'markdown links' }),
|
||||
pnpmScript('doc-refs', 'verify-doc-refs', { label: 'doc refs' }),
|
||||
pnpmScript('package-paths', 'verify-package-paths', { label: 'package paths' }),
|
||||
pnpmScript('package-readme-model-experience', 'verify-package-readme-model-experience', { label: 'package README model experience' }),
|
||||
pnpmScript('mermaid', 'verify-mermaid'),
|
||||
pnpmScript('rfc-classification', 'verify-rfc-classification', { label: 'rfc classification' }),
|
||||
pnpmScript('rfc-format', 'verify-rfc-format', { label: 'rfc format' }),
|
||||
pnpmScript('type-equivalence', 'verify-type-equiv', { label: 'type equivalence' }),
|
||||
pnpmScript('translation-prompt', 'verify-translation-prompt', { label: 'translation prompt' }),
|
||||
pnpmScript('translation-pairing', 'verify-translation-pairing', { label: 'translation pairing' }),
|
||||
pnpmScript('doc-budgets', 'verify-doc-budgets', { label: 'doc budgets' }),
|
||||
pnpmScript('package-readme-limitations', 'verify-package-readme-limitations', { label: 'package README limitations' }),
|
||||
pnpmScript('website-yaml', 'verify-website-yaml', { label: 'website yaml' }),
|
||||
]
|
||||
}
|
||||
@@ -284,24 +310,33 @@ function demoSmokeGate(options: { needs?: string[] } = {}): Gate {
|
||||
return {
|
||||
id: 'demo-smoke',
|
||||
label: 'demo smoke',
|
||||
command: pnpmBin(),
|
||||
args: ['run', 'demo:echo'],
|
||||
...pnpmInvocation(['run', 'demo:echo']),
|
||||
input: 'echo ci smoke\n',
|
||||
...dependencyOptions,
|
||||
verify: async (result) => {
|
||||
const output = result.stdout + result.stderr
|
||||
if (!output.includes('[tool call] echo({"text":"ci smoke"})')) {
|
||||
throw new Error('demo smoke did not show the echo tool call.')
|
||||
const sessionsRoot = join(root, '.sessions')
|
||||
try {
|
||||
if (!output.includes('[tool call] echo({"text":"ci smoke"})')) {
|
||||
throw new Error('demo smoke did not show the echo tool call.')
|
||||
}
|
||||
if (!output.includes('[tool result] ECHO: CI SMOKE')) {
|
||||
throw new Error('demo smoke did not show the echo tool result.')
|
||||
}
|
||||
const buckets = await readdir(sessionsRoot, { withFileTypes: true })
|
||||
let found = false
|
||||
for (const bucket of buckets) {
|
||||
if (!bucket.isDirectory() || !bucket.name.startsWith('cwd-')) continue
|
||||
const entries = await readdir(join(sessionsRoot, bucket.name))
|
||||
if (entries.some(entry => /^main-session-.+\.jsonl$/.test(entry))) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!found) throw new Error('demo smoke did not create a main-session JSONL log in a cwd bucket.')
|
||||
} finally {
|
||||
await rm(sessionsRoot, { recursive: true, force: true })
|
||||
}
|
||||
if (!output.includes('[tool result] ECHO: CI SMOKE')) {
|
||||
throw new Error('demo smoke did not show the echo tool result.')
|
||||
}
|
||||
const sessionDir = join(root, '.sessions', '_no-cwd')
|
||||
const entries = await readdir(sessionDir)
|
||||
if (!entries.some(entry => /^main-session-.+\.jsonl$/.test(entry))) {
|
||||
throw new Error('demo smoke did not create a main-session JSONL log.')
|
||||
}
|
||||
await rm(join(root, '.sessions'), { recursive: true, force: true })
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -312,10 +347,10 @@ function builtBinSmokeGate(): Gate {
|
||||
'run',
|
||||
'--config',
|
||||
'vitest.e2e.config.ts',
|
||||
'packages/ui/stdio-agent/tests/built-bin.e2e.ts',
|
||||
'packages/ui/acp-agent/tests/built-bin.e2e.ts',
|
||||
'packages/examples/stdio-demo/tests/built-bin.e2e.ts',
|
||||
'packages/examples/acp-demo/tests/built-bin.e2e.ts',
|
||||
// The worker-entry packages' built bundles: the only automated proof
|
||||
// that lib/index.js resolves its sibling lib/worker.js under plain node
|
||||
// that lib/index.js resolves its sibling lib/worker.cjs under plain node
|
||||
// (the e2e lane runs unbuilt, so these files self-skip there).
|
||||
'packages/workflow/workflow-workerthread/tests/built-worker.e2e.ts',
|
||||
'packages/code-runtime/code-runtime-worker/tests/built-lib.e2e.ts',
|
||||
|
||||
Reference in New Issue
Block a user