Gate JSDoc completeness on every package export

New doc-sync gate verify-export-jsdoc walks every module-level exported
name under packages/*/*/src and requires description prose everywhere,
plus @param per parameter and @returns on non-void annotated returns for
function-like exports, public class methods, properties, and accessors.
The parsing + check helpers move out of gen-cordis-catalog.ts into a
shared scripts/jsdoc.ts so 'documented' means one thing on both gated
surfaces.

Deliberate exemptions (documented in the RFC): heritage-declared class
members (the seam declaration is the doc's one home — the one checker
query in an otherwise pure-AST walk), cordis plugin-protocol slots
(name/inject/reusable/Config/apply, top-level and static), constructors,
overload implementations, declare-module augmentation bodies, and
re-export statements (checked at the defining module).

The 203 under-documented exports the gate found at adoption are filled
in this change, so the gate lands green; generated catalogs/graphs are
regenerated for the shifted line pointers.

RFC: docs/rfc/implemented/process/2026-07-06-export-surface-jsdoc-gate.md
This commit is contained in:
Tianyi Cui
2026-07-06 22:09:30 +08:00
parent 1c999804d8
commit cd9737d569
92 changed files with 1802 additions and 289 deletions

View File

@@ -121,7 +121,12 @@ export const DEFAULT_DISPOSE_GRACE_MS = 3_000
*/
export const SENSITIVE_ENV_PATTERN = /KEY|SECRET|TOKEN/i
/** The ambient env minus credential-shaped vars, plus the spec's explicit env. */
/**
* The ambient env minus credential-shaped vars, plus the spec's explicit env.
* @param extra - explicit vars layered on top AFTER the scrub, so a
* credential-shaped name supplied deliberately still reaches the child.
* @returns the environment to spawn the child with.
*/
export function buildChildEnv(extra: Record<string, string>): NodeJS.ProcessEnv {
const env: NodeJS.ProcessEnv = {}
for (const [key, value] of Object.entries(process.env)) {
@@ -130,7 +135,12 @@ export function buildChildEnv(extra: Record<string, string>): NodeJS.ProcessEnv
return { ...env, ...extra }
}
/** Map an ACP {@link StopReason} to a harness {@link SubagentStopReason}. */
/**
* Map an ACP {@link StopReason} to a harness {@link SubagentStopReason}.
* @param reason - the terminal reason from the child's `session/prompt` response.
* @returns the harness equivalent; `max_turn_requests` and any unknown future
* variant map to `error`, so an unclean stop is never reported as `completed`.
*/
export function acpStopReason(reason: StopReason): SubagentStopReason {
switch (reason) {
case 'end_turn':
@@ -155,12 +165,20 @@ export function acpStopReason(reason: StopReason): SubagentStopReason {
}
}
/** Collect the text of an ACP content block (non-text blocks contribute nothing). */
/**
* Collect the text of an ACP content block (non-text blocks contribute nothing).
* @param content - the content block off a streamed `agent_message_chunk`.
* @returns the block's text, or `''` for a non-text block.
*/
export function acpContentText(content: AcpContentBlock): string {
return content.type === 'text' ? content.text : ''
}
/** Translate the harness prompt blocks into ACP prompt blocks (text only). */
/**
* Translate the harness prompt blocks into ACP prompt blocks (text only).
* @param prompt - the harness prompt; non-text blocks are dropped.
* @returns the ACP text blocks, in order.
*/
export function toAcpPrompt(prompt: ContentBlock[]): AcpContentBlock[] {
const blocks: AcpContentBlock[] = []
for (const block of prompt) {
@@ -206,6 +224,11 @@ function exitsWithin(child: ChildProcess, ms: number): Promise<boolean> {
* failure (a spawn/transport/RPC error resolves with `stopReason: 'error'`), per
* the seam contract. `cancel()` sends `session/cancel`; `dispose()` kills the
* subprocess and awaits its exit (quiescent teardown).
* @param request - the start request; the driver consumes `prompt` and `signal`
* (an already-aborted signal yields an inert `aborted` run with no spawn).
* @param spec - the resolved spawn spec: command/args/cwd, env, permission
* policy, dispose graces, and the optional error sink.
* @returns the live run handle for the child subprocess.
*/
export function startAcpRun(request: SubagentStartRequest, spec: AcpRunSpec): SubagentRun {
const id = AgentId(randomUUID())

View File

@@ -47,6 +47,8 @@ export const Config: z<Config> = z.object({
* empty — i.e. fresh — child). The result is contiguous from seq 0 (the live
* log keeps `seq === index`), so it is a valid session seed; the in-flight,
* unbalanced turn is dropped so the invariants replay accepts it.
* @param parent - the agent whose session log to slice.
* @returns the seed events, contiguous from seq 0; empty when no turn has completed.
*/
export function completedTurnPrefix(parent: Agent): SessionEvent[] {
const events = parent.session.events

View File

@@ -34,7 +34,11 @@ declare module '@deepseek-ai/dsh-agent' {
}
}
/** Read an agent's delegation depth (absent ⇒ a top-level agent, depth 0). */
/**
* Read an agent's delegation depth (absent ⇒ a top-level agent, depth 0).
* @param agent - the agent whose options may carry `subagentDepth`.
* @returns 0 for a top-level agent, its parent's depth + 1 for a subagent.
*/
export function depthOf(agent: Agent): number {
return agent.options.subagentDepth ?? 0
}
@@ -88,6 +92,13 @@ export interface InProcessRunOptions {
* the matching `turn/end.reason` the stop reason. `dispose()` delegates to the
* factory's {@link AgentHandle.dispose} (stop loop → await quiescence → remove
* session); `cancel()` cancels the child's in-flight turn.
*
* Throws {@link SubagentDepthError} before creating anything when the child's
* depth (parent depth + 1) would exceed `request.maxDepth`.
* @param ctx - the context whose `agents` factory creates and owns the child.
* @param request - the start request (prompt, parent, signal, per-child options).
* @param options - the backend's inputs: provider name plus the optional seed.
* @returns the live run handle for the child agent.
*/
export function startInProcessRun(
ctx: Context,

View File

@@ -93,6 +93,7 @@ export interface SubagentStopReasonMap {
refusal: 'refusal'
}
/** The union over {@link SubagentStopReasonMap} — widens automatically as backends merge in variants. */
export type SubagentStopReason = SubagentStopReasonMap[keyof SubagentStopReasonMap]
/**