docs: deduplicate paired code-block checks

This commit is contained in:
Tianyi Cui
2026-07-26 02:52:48 +08:00
parent 633ceaf41b
commit f2cf29bd04
18 changed files with 175 additions and 971 deletions

View File

@@ -1,7 +1,8 @@
/**
* Typecheck Markdown `ts` fences against the workspace API. `ignore-check` fences are reported as
* opt-outs; generated catalog fragments and source-equivalence blocks are skipped here because their
* owning gates verify them. A build-coordinated mode consumes existing declarations without emit.
* owning gates verify them. Byte-identical `.zh.md` copies reuse their unsuffixed sibling's check. A
* build-coordinated mode consumes existing declarations without emit.
*/
import { execFileSync } from 'node:child_process'
@@ -10,6 +11,7 @@ import { join, relative, resolve } from 'node:path'
import ts from 'typescript'
import { builtDeclarationPath } from './doc-typecheck-paths.ts'
import { extractFences } from './md-fences.ts'
import { partitionPairedMarkdownDerivatives } from './paired-markdown-derivatives.ts'
const root = resolve(import.meta.dirname, '..')
@@ -206,7 +208,12 @@ for (const pattern of markdownGlobs) {
}
files.sort()
const all = files.flatMap(extractBlocks)
const extracted = files.flatMap(extractBlocks)
const { primary: all, derivatives } = partitionPairedMarkdownDerivatives(
extracted,
block => block.file,
block => `${block.kind}\0${block.code}`,
)
const checked = all.filter(b => b.kind === 'check')
const ignored = all.filter(b => b.kind === 'ignore')
// Only compile-eligible fences belong in the opt-out ratio; every other skipped
@@ -233,7 +240,7 @@ if (compilationError !== undefined) {
const ratio = ignored.length / ratioDenominator
const skipped = all.length - ratioDenominator
console.log(`doc-typecheck: ${checked.length} block(s) compiled, ${ignored.length} ignored (${(ratio * 100).toFixed(0)}% opt-out), ${skipped} type-equiv/catalog (checked elsewhere).`)
console.log(`doc-typecheck: ${checked.length} block(s) compiled, ${ignored.length} ignored (${(ratio * 100).toFixed(0)}% opt-out), ${skipped} type-equiv/catalog (checked elsewhere), ${derivatives.length} paired derivative(s).`)
// Guard against the escape hatch becoming the norm.
if (ratioDenominator >= 4 && ratio > 0.5) {
console.error(`doc-typecheck: too many blocks opt out of checking (${ignored.length}/${ratioDenominator}). Make them compile or delete them.`)

View File

@@ -0,0 +1,66 @@
import { describe, expect, it } from 'vitest'
import { partitionPairedMarkdownDerivatives } from './paired-markdown-derivatives.ts'
interface Block {
doc: string
kind: string
code: string
}
const partition = (blocks: Block[]) => partitionPairedMarkdownDerivatives(
blocks,
block => block.doc,
block => `${block.kind}\0${block.code}`,
)
describe('partitionPairedMarkdownDerivatives', () => {
it('treats a complete byte-identical Chinese sequence as derivative', () => {
const english = [
{ doc: 'docs/example.md', kind: 'ts', code: 'const one = 1' },
{ doc: 'docs/example.md', kind: 'type-equiv', code: 'interface Example {}' },
]
const chinese = english.map(block => ({ ...block, doc: 'docs/example.zh.md' }))
const unrelated = { doc: 'docs/other.md', kind: 'ts', code: 'const other = 2' }
expect(partition([...english, ...chinese, unrelated])).toEqual({
primary: [...english, unrelated],
derivatives: chinese,
})
})
it('keeps reordered, changed, partial, and orphan Chinese sequences primary', () => {
const sequence = (doc: string) => [
{ doc, kind: 'ts', code: 'const one = 1' },
{ doc, kind: 'ts', code: 'const two = 2' },
]
const english = sequence('docs/example.md')
const changed = english.map((block, index) => ({
...block,
doc: 'docs/example.zh.md',
code: index === 0 ? 'const one = 0' : block.code,
}))
const reorderedEnglish = sequence('docs/reordered.md')
const reordered = [...reorderedEnglish].reverse().map(block => ({ ...block, doc: 'docs/reordered.zh.md' }))
const partialEnglish = sequence('docs/partial.md')
const partial = [{ ...partialEnglish[0]!, doc: 'docs/partial.zh.md' }]
const orphan = [{ doc: 'docs/orphan.zh.md', kind: 'ts', code: 'const orphan = true' }]
const blocks = [
...english,
...changed,
...reorderedEnglish,
...reordered,
...partialEnglish,
...partial,
...orphan,
]
expect(partition(blocks)).toEqual({ primary: blocks, derivatives: [] })
})
it('requires the fence kind to match as well as the body', () => {
const english = { doc: 'docs/example.md', kind: 'type-equiv', code: 'interface Example {}' }
const chinese = { ...english, doc: 'docs/example.zh.md', kind: 'public-api' }
expect(partition([english, chinese])).toEqual({ primary: [english, chinese], derivatives: [] })
})
})

View File

@@ -0,0 +1,63 @@
/**
* Separate byte-identical Chinese Markdown code blocks from the primary checks
* performed on their unsuffixed English siblings. The bilingual pairing gate
* owns cross-language identity; source-oriented gates consume one copy.
*/
/** The result of separating canonical blocks from paired Chinese derivatives. */
export interface MarkdownDerivativePartition<T> {
/** Blocks that still require the caller's owning check. */
primary: T[]
/** Chinese blocks covered by the byte-identical unsuffixed sequence. */
derivatives: T[]
}
/** Return the unsuffixed sibling of a Chinese Markdown path. */
function unsuffixedSibling(doc: string): string | null {
return doc.endsWith('.zh.md') ? `${doc.slice(0, -'.zh.md'.length)}.md` : null
}
/**
* Partition complete byte-identical `.zh.md` block sequences from primary
* blocks. A partial or reordered match stays primary so the caller fails
* closed; the translation-pairing gate reports the cross-language mismatch.
*
* @param blocks - Blocks in repository scan order.
* @param docOf - Repository-relative Markdown path owning a block.
* @param fingerprintOf - Block kind/info string plus byte-exact body.
* @returns Primary blocks and paired Chinese derivatives, preserving order.
*/
export function partitionPairedMarkdownDerivatives<T>(
blocks: readonly T[],
docOf: (block: T) => string,
fingerprintOf: (block: T) => string,
): MarkdownDerivativePartition<T> {
const byDoc = new Map<string, T[]>()
for (const block of blocks) {
const doc = docOf(block)
const group = byDoc.get(doc)
if (group) group.push(block)
else byDoc.set(doc, [block])
}
const derivativeDocs = new Set<string>()
for (const [doc, candidates] of byDoc) {
const sibling = unsuffixedSibling(doc)
if (sibling === null) continue
const originals = byDoc.get(sibling)
if (originals === undefined || originals.length !== candidates.length) continue
if (candidates.every((candidate, index) => {
const original = originals[index]
return original !== undefined && fingerprintOf(candidate) === fingerprintOf(original)
})) {
derivativeDocs.add(doc)
}
}
const primary: T[] = []
const derivatives: T[] = []
for (const block of blocks) {
(derivativeDocs.has(docOf(block)) ? derivatives : primary).push(block)
}
return { primary, derivatives }
}

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
{
"comment": "Maps each ` ```ts type-equiv ` or ` ```ts public-api ` block (by doc + declared symbol + projection) to the source declaration and original JSDoc it must match. Omit projection for the complete declaration; use public-api with a ` ```ts public-api ` block for a body-stripped public class declaration. verify-type-equiv.ts enforces a 1:1 correspondence: every source-equivalence block has exactly one entry here, and every entry resolves to exactly one block. Add an entry when you add a source-equivalence block; remove it when you remove the block.",
"comment": "Maps each primary ` ```ts type-equiv ` or ` ```ts public-api ` block (by doc + declared symbol + projection) to the source declaration and original JSDoc it must match. Paired `.zh.md` blocks are byte-identical derivatives checked through their unsuffixed sibling and have no duplicate entry. Omit projection for the complete declaration; use public-api with a ` ```ts public-api ` block for a body-stripped public class declaration. verify-type-equiv.ts enforces a 1:1 correspondence between primary blocks and entries. Add an entry when you add a primary source-equivalence block; remove it when you remove the block.",
"entries": [
{
"doc": "docs/core-data-structures/core.md",
@@ -1248,949 +1248,6 @@
"doc": "docs/core-data-structures/session-query.md",
"symbol": "SessionSearchHit",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "Branded",
"source": "packages/util/brand/src/index.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "ContentBlockMap",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "AssistantProvenance",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "Message",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "MessageSourceMap",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "FinishReasonMap",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "LlmProviderInfo",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "LlmModelInfo",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "LlmModelContext",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "GenerateOptions",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "ToolSchema",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "LlmCallConfig",
"source": "packages/llm/llm/src/call-config.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "SessionEvent",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "SendOptions",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "AgentCancelCause",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "InjectOptions",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "ResolvedAgentInput",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "AgentMessageId",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "AgentMessage",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "CancelOptions",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "Agent",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "HookContext",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "PromptDecision",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "ContinuationDecision",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "RequestError",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "RequestErrorDecision",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "ContinuationStop",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/core.zh.md",
"symbol": "SessionStartSource",
"source": "packages/core/agent/src/types.ts"
},
{
"doc": "docs/core-data-structures/scope.zh.md",
"symbol": "ScopeKey",
"source": "packages/core/scope/src/index.ts"
},
{
"doc": "docs/core-data-structures/scope.zh.md",
"symbol": "Scoped",
"source": "packages/core/scope/src/index.ts"
},
{
"doc": "docs/core-data-structures/scope.zh.md",
"symbol": "Scope",
"source": "packages/core/scope/src/index.ts"
},
{
"doc": "docs/core-data-structures/scope.zh.md",
"symbol": "ScopeLayer",
"source": "packages/core/scope/src/store.ts"
},
{
"doc": "docs/core-data-structures/system-prompt.zh.md",
"symbol": "AssembleContext",
"source": "packages/core/system-prompt/src/index.ts"
},
{
"doc": "docs/core-data-structures/system-prompt.zh.md",
"symbol": "PromptSection",
"source": "packages/core/system-prompt/src/index.ts"
},
{
"doc": "docs/core-data-structures/system-prompt.zh.md",
"symbol": "ToolProviderResult",
"source": "packages/core/system-prompt/src/index.ts"
},
{
"doc": "docs/core-data-structures/llm-streaming.zh.md",
"symbol": "StreamChunk",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/llm-streaming.zh.md",
"symbol": "LlmFailure",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/llm-streaming.zh.md",
"symbol": "TokenUsage",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/llm-streaming.zh.md",
"symbol": "ContentBlockMap",
"source": "packages/llm/llm/src/types.ts"
},
{
"doc": "docs/core-data-structures/llm-streaming.zh.md",
"symbol": "AppIdentity",
"source": "packages/llm/llm/src/attribution.ts"
},
{
"doc": "docs/core-data-structures/llm-streaming.zh.md",
"symbol": "BlockAssembler",
"source": "packages/llm/llm/src/assembler.ts",
"projection": "public-api"
},
{
"doc": "docs/core-data-structures/llm-streaming.zh.md",
"symbol": "LlmAdapter",
"source": "packages/llm/llm/src/index.ts",
"projection": "public-api"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "PromptMessageData",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SessionEventMap",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "OutOfBandSessionEventMap",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "EpochHeader",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "TodoItem",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SessionEvent",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "TurnTriggerMap",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "TurnEndReasonMap",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SurfaceEventType",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SurfaceOp",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SurfaceIntent",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SessionSurface",
"source": "packages/core/session/src/surface.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SurfaceFoldReplacement",
"source": "packages/core/session/src/surface.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "SurfaceFoldResult",
"source": "packages/core/session/src/surface.ts"
},
{
"doc": "docs/core-data-structures/session.zh.md",
"symbol": "Session",
"source": "packages/core/session/src/index.ts",
"projection": "public-api"
},
{
"doc": "docs/core-data-structures/persistence.zh.md",
"symbol": "SessionHeader",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/persistence.zh.md",
"symbol": "CreateSessionOptions",
"source": "packages/core/session/src/types.ts"
},
{
"doc": "docs/core-data-structures/persistence.zh.md",
"symbol": "SessionLocation",
"source": "packages/session-persistence/session-persistence/src/index.ts"
},
{
"doc": "docs/core-data-structures/persistence.zh.md",
"symbol": "SessionPersistenceRevision",
"source": "packages/session-persistence/session-persistence/src/revision.ts"
},
{
"doc": "docs/core-data-structures/persistence.zh.md",
"symbol": "SessionPersistenceSnapshot",
"source": "packages/session-persistence/session-persistence/src/index.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventSurface",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionRecord",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionLogSnapshot",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionSurfaceSnapshot",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionTitleObservation",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionTitleObservationResult",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventRecord",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionResultFilter",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventResultFilter",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventSearchDocument",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionSearchCursor",
"source": "packages/session-query/session-query/src/cursor.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionSearchRequest",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventSearchRequest",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionSearchPage",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventSearchPage",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventSearchHit",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionSearchHit",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionLineageNode",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionLineageTrace",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionQueryErrorCode",
"source": "packages/session-query/session-query/src/config.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventReadRequest",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventWindow",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventTraceRequest",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventTrace",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/session-query.zh.md",
"symbol": "SessionEventTraceObservation",
"source": "packages/session-query/session-query/src/types.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolOutputDefinition",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolDefinition",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ValueSchemaSpec",
"source": "packages/core/tools/src/schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ParameterPropertySpec",
"source": "packages/core/tools/src/schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ParameterSchemaSpec",
"source": "packages/core/tools/src/schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "InferValue",
"source": "packages/core/tools/src/schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "InferArgs",
"source": "packages/core/tools/src/schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolExecutionToken",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolExecutionInput",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolExecution",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolDispatchExecution",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolExecutionMode",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolRunContext",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolGuard",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolRestriction",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolFailure",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolExecutionSuccess",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolExecutionFailure",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ToolExecutionResult",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "PreToolDecision",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "PostToolDecision",
"source": "packages/core/tools/src/index.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "JsonSchemaScalar",
"source": "packages/core/tools/src/json-schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "JsonSchemaType",
"source": "packages/core/tools/src/json-schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "JsonSchemaNode",
"source": "packages/core/tools/src/json-schema.ts"
},
{
"doc": "docs/core-data-structures/tools.zh.md",
"symbol": "ObjectJsonSchema",
"source": "packages/core/tools/src/json-schema.ts"
},
{
"doc": "docs/core-data-structures/user-interaction.zh.md",
"symbol": "AskUserQuestionOption",
"source": "packages/ui/user-interaction/src/types.ts"
},
{
"doc": "docs/core-data-structures/user-interaction.zh.md",
"symbol": "AskUserQuestionItem",
"source": "packages/ui/user-interaction/src/types.ts"
},
{
"doc": "docs/core-data-structures/user-interaction.zh.md",
"symbol": "AskUserQuestionRequest",
"source": "packages/ui/user-interaction/src/index.ts"
},
{
"doc": "docs/core-data-structures/user-interaction.zh.md",
"symbol": "AskUserQuestionAnswerItem",
"source": "packages/ui/user-interaction/src/types.ts"
},
{
"doc": "docs/core-data-structures/user-interaction.zh.md",
"symbol": "AskUserQuestionAnswer",
"source": "packages/ui/user-interaction/src/types.ts"
},
{
"doc": "docs/core-data-structures/user-interaction.zh.md",
"symbol": "UserInteractionProvider",
"source": "packages/ui/user-interaction/src/index.ts"
},
{
"doc": "docs/core-data-structures/user-interaction.zh.md",
"symbol": "UserInteractionError",
"source": "packages/ui/user-interaction/src/index.ts"
},
{
"doc": "docs/core-data-structures/approval.zh.md",
"symbol": "ApprovalRequestId",
"source": "packages/ui/user-approval/src/types.ts"
},
{
"doc": "docs/core-data-structures/approval.zh.md",
"symbol": "ApprovalOutcome",
"source": "packages/ui/user-approval/src/types.ts"
},
{
"doc": "docs/core-data-structures/approval.zh.md",
"symbol": "ApprovalPolicy",
"source": "packages/ui/user-approval/src/index.ts"
},
{
"doc": "docs/core-data-structures/approval.zh.md",
"symbol": "ApprovalRequest",
"source": "packages/ui/user-approval/src/index.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "DshEnvironmentKey",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "DshEnvironment",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "BashExecRequest",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "BashExecSpec",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "BashRunResult",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "BashSandboxInfo",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "CollectedOutput",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "BashProcess",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/bash.zh.md",
"symbol": "BashProcessRead",
"source": "packages/bash/bash/src/types.ts"
},
{
"doc": "docs/core-data-structures/sandbox.zh.md",
"symbol": "SandboxMode",
"source": "packages/sandbox/sandbox/src/index.ts"
},
{
"doc": "docs/core-data-structures/sandbox.zh.md",
"symbol": "ConfinedSandboxMode",
"source": "packages/sandbox/sandbox/src/index.ts"
},
{
"doc": "docs/core-data-structures/sandbox.zh.md",
"symbol": "SandboxExecutionPolicy",
"source": "packages/sandbox/sandbox/src/index.ts"
},
{
"doc": "docs/core-data-structures/sandbox.zh.md",
"symbol": "SandboxEnforcement",
"source": "packages/sandbox/sandbox/src/index.ts"
},
{
"doc": "docs/core-data-structures/sandbox.zh.md",
"symbol": "SandboxPolicy",
"source": "packages/sandbox/sandbox/src/index.ts"
},
{
"doc": "docs/core-data-structures/sandbox.zh.md",
"symbol": "SandboxPolicyRequest",
"source": "packages/sandbox/sandbox-policy/src/index.ts"
},
{
"doc": "docs/core-data-structures/sandbox.zh.md",
"symbol": "ConfinedArgv",
"source": "packages/sandbox/sandbox/src/index.ts"
},
{
"doc": "docs/core-data-structures/code-runtime.zh.md",
"symbol": "CodeJsonValue",
"source": "packages/code-runtime/code-runtime/src/types.ts"
},
{
"doc": "docs/core-data-structures/code-runtime.zh.md",
"symbol": "CodeRunRequest",
"source": "packages/code-runtime/code-runtime/src/types.ts"
},
{
"doc": "docs/core-data-structures/code-runtime.zh.md",
"symbol": "CodeRunResult",
"source": "packages/code-runtime/code-runtime/src/types.ts"
},
{
"doc": "docs/core-data-structures/code-runtime.zh.md",
"symbol": "CodeBindingNamespace",
"source": "packages/code-runtime/code-runtime/src/types.ts"
},
{
"doc": "docs/core-data-structures/code-runtime.zh.md",
"symbol": "CodeBindingErrorClass",
"source": "packages/code-runtime/code-runtime/src/types.ts"
},
{
"doc": "docs/core-data-structures/code-runtime.zh.md",
"symbol": "CodeBindingFunction",
"source": "packages/code-runtime/code-runtime/src/types.ts"
},
{
"doc": "docs/core-data-structures/code-runtime.zh.md",
"symbol": "CodeRunFailure",
"source": "packages/code-runtime/code-runtime/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsTarget",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsTargetKey",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsVersion",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsInfo",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsPathInfo",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsDirEntry",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsWriteIntent",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsWriteOutcome",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsEditRequest",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsEditOutcome",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsErrorCode",
"source": "packages/fs/fs/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FsPolicyExec",
"source": "packages/fs/fs-policy/src/types.ts"
},
{
"doc": "docs/core-data-structures/filesystem.zh.md",
"symbol": "FileReadOutcome",
"source": "packages/fs/tool-fs/src/read-render.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillSource",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillResourceBase",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillSummary",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillCandidate",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillDefinition",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillRegistration",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillLookupOptions",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "SkillProvider",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/skills.zh.md",
"symbol": "Config",
"source": "packages/skill/skill/src/index.ts"
},
{
"doc": "docs/core-data-structures/compaction.zh.md",
"symbol": "CompactionResult",
"source": "packages/compact/compact/src/types.ts"
},
{
"doc": "docs/core-data-structures/compaction.zh.md",
"symbol": "CompactionTrigger",
"source": "packages/compact/compact/src/index.ts"
},
{
"doc": "docs/core-data-structures/compaction.zh.md",
"symbol": "PrunedEntry",
"source": "packages/compact/compact-tool-result-prune/src/types.ts"
},
{
"doc": "docs/core-data-structures/compaction.zh.md",
"symbol": "PruneResult",
"source": "packages/compact/compact-tool-result-prune/src/types.ts"
},
{
"doc": "docs/core-data-structures/subagent.zh.md",
"symbol": "SubagentCapabilities",
"source": "packages/subagent/subagent/src/types.ts"
},
{
"doc": "docs/core-data-structures/subagent.zh.md",
"symbol": "SubagentStartRequest",
"source": "packages/subagent/subagent/src/types.ts"
},
{
"doc": "docs/core-data-structures/subagent.zh.md",
"symbol": "SubagentResult",
"source": "packages/subagent/subagent/src/types.ts"
},
{
"doc": "docs/core-data-structures/subagent.zh.md",
"symbol": "SubagentStopReasonMap",
"source": "packages/subagent/subagent/src/types.ts"
},
{
"doc": "docs/core-data-structures/subagent.zh.md",
"symbol": "SubagentRun",
"source": "packages/subagent/subagent/src/types.ts"
},
{
"doc": "docs/core-data-structures/subagent.zh.md",
"symbol": "SubagentProvider",
"source": "packages/subagent/subagent/src/types.ts"
},
{
"doc": "docs/core-data-structures/web.zh.md",
"symbol": "WebSearchRequest",
"source": "packages/web/web/src/types.ts"
},
{
"doc": "docs/core-data-structures/web.zh.md",
"symbol": "WebSearchResult",
"source": "packages/web/web/src/types.ts"
},
{
"doc": "docs/core-data-structures/web.zh.md",
"symbol": "WebSearchSource",
"source": "packages/web/web/src/types.ts"
},
{
"doc": "docs/core-data-structures/web.zh.md",
"symbol": "WebFetchRequest",
"source": "packages/web/web/src/types.ts"
},
{
"doc": "docs/core-data-structures/web.zh.md",
"symbol": "WebFetchResult",
"source": "packages/web/web/src/types.ts"
},
{
"doc": "docs/core-data-structures/web.zh.md",
"symbol": "WebFetchBody",
"source": "packages/web/web/src/types.ts"
},
{
"doc": "docs/core-data-structures/workflow.zh.md",
"symbol": "WorkflowStartRequest",
"source": "packages/workflow/workflow/src/types.ts"
},
{
"doc": "docs/core-data-structures/workflow.zh.md",
"symbol": "WorkflowMeta",
"source": "packages/workflow/workflow/src/types.ts"
},
{
"doc": "docs/core-data-structures/workflow.zh.md",
"symbol": "WorkflowResult",
"source": "packages/workflow/workflow/src/types.ts"
},
{
"doc": "docs/core-data-structures/workflow.zh.md",
"symbol": "WorkflowRun",
"source": "packages/workflow/workflow/src/types.ts"
}
]
}

View File

@@ -4,12 +4,14 @@
* declaration; `public-api` entries preserve a class's body-stripped public
* declaration. Blocks and entries have a one-to-one relationship; comparison
* ignores whitespace and non-JSDoc comments but preserves declaration
* structure and every original JSDoc comment.
* structure and every original JSDoc comment. Byte-identical `.zh.md` blocks
* reuse the manifest-backed check of their unsuffixed sibling.
*/
import { globSync, readFileSync, existsSync } from 'node:fs'
import { resolve, sep } from 'node:path'
import ts from 'typescript'
import { partitionPairedMarkdownDerivatives } from './paired-markdown-derivatives.ts'
const root = resolve(import.meta.dirname, '..')
@@ -223,7 +225,12 @@ const docSet = new Set<string>()
for (const pattern of MARKDOWN_GLOBS) {
for (const match of globSync(pattern, { cwd: root })) docSet.add(match.split(sep).join('/'))
}
const blocks: EquivBlock[] = [...docSet].sort().flatMap(extractEquivBlocks)
const extractedBlocks: EquivBlock[] = [...docSet].sort().flatMap(extractEquivBlocks)
const { primary: blocks, derivatives } = partitionPairedMarkdownDerivatives(
extractedBlocks,
block => block.doc,
block => `${block.projection ?? 'declaration'}\0${block.code}`,
)
const errors: string[] = []
// A manifest entry naming a doc that does not exist (or is outside the scanned
@@ -299,11 +306,11 @@ for (const e of entries) {
}
if (errors.length === 0) {
console.log(`verify-type-equiv: ${verified} type-equiv block(s) match source structure and JSDoc (1:1 with manifest).`)
console.log(`verify-type-equiv: ${verified} type-equiv block(s) match source structure and JSDoc (1:1 with manifest); ${derivatives.length} paired derivative(s).`)
process.exit(0)
}
console.error('verify-type-equiv: type-equiv verification failed:')
for (const e of errors) console.error(` ${e}`)
console.error(`\n(checked ${blocks.length} block(s) across ${new Set(blocks.map(b => b.doc)).size} doc(s); manifest at scripts/type-equiv.manifest.json)`)
console.error(`\n(checked ${blocks.length} primary block(s) across ${new Set(blocks.map(b => b.doc)).size} doc(s), ${derivatives.length} paired derivative(s); manifest at scripts/type-equiv.manifest.json)`)
process.exit(1)