docs: make technical prose concrete

This commit is contained in:
Turtle
2026-08-09 15:27:21 +08:00
parent 673e7cddc5
commit a27efdef36
459 changed files with 1342 additions and 1329 deletions

View File

@@ -1,3 +1,3 @@
# AGENTS.md — Repository scripts
Gate scripts invoke pnpm shell-free, normalize repository-relative glob paths to `/` at ingestion, and keep platform adaptation at the owning gate boundary instead of a shared platform layer.
Gate scripts invoke pnpm shell-free, normalize repository-relative glob paths to `/` at ingestion, and keep platform adaptation in the gate that needs it instead of a shared platform layer.

View File

@@ -4,7 +4,7 @@ import { createHash } from 'node:crypto'
import { basename } from 'node:path'
import { AGENT_NOTE_CLASSES } from './agent-note-tree.ts'
/** Versioned shape of the frozen-content manifest. */
/** Versioned fields in the frozen-content manifest. */
export interface ArchiveManifest {
version: 1
files: Readonly<Record<string, string>>

View File

@@ -1,5 +1,5 @@
/**
* Pins shared client-bundle preset contracts: the module-edge purity gate and
* Pins shared client-bundle preset rules: the module-edge purity gate and
* the physical watch dependencies hidden behind virtual CSS Modules.
*/
import { fileURLToPath } from 'node:url'

View File

@@ -81,7 +81,7 @@ export function contextKeyMap(body: ts.ModuleBlock, sf: ts.SourceFile): Map<stri
/**
* Every event name a `declare module 'cordis'` Events merge declares in one
* module body. Names are the literal member keys (`'agent/created'`), read
* from method and property members alike so a declaration shape the projector
* from method and property members alike so a declaration form the projector
* would reject still enters the exhaustiveness scan.
* @param body - The cordis module augmentation block.
* @param sf - Owning source file (for computed-name text extraction).

View File

@@ -1,6 +1,6 @@
/**
* Heavy suites the coverage aggregate runs uninstrumented in a parallel gate.
* Membership contract: a suite qualifies only when every coverage-measured
* Membership rule: a suite qualifies only when every coverage-measured
* file it executes in-process (`coverage.include` spans package src trees;
* typert generator src is threshold-excluded in vitest.config.ts) is already
* fully covered by other suites, so removing it from the instrumented run

View File

@@ -1,6 +1,6 @@
/** Map one workspace source alias target to its declaration-build target. */
export function builtDeclarationPath(candidate: string): string {
// Two workspace shapes exist: whole-package entries end in /src, subpath
// Two workspace path forms exist: whole-package entries end in /src, subpath
// wildcards (apiproxy's browser-safe /api and /client channels) in /src/*.
if (candidate.endsWith('/src')) {
return `${candidate.slice(0, -'/src'.length)}/lib/types`

View File

@@ -221,7 +221,7 @@ const { primary: all, derivatives } = partitionPairedMarkdownDerivatives(
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
// kind has an independent verifier named in BlockKind's contract above.
// kind has an independent verifier named in the BlockKind rules above.
const ratioDenominator = checked.length + ignored.length
if (checked.length === 0) {

View File

@@ -2,7 +2,7 @@
* Generate `docs/config-catalog.md` from package entry points, config types,
* JSDoc, and static Schemastery schemas. Every package must classify, referenced
* types must resolve without collisions, and every enumerable schema path must
* exist on the declared config type. External and dynamic shapes stay unknown;
* exist on the declared config type. External and dynamic types stay unknown;
* declared runtime-only fields need not appear in the schema. `--check` verifies
* the committed artifact.
*/
@@ -220,7 +220,7 @@ interface World {
}
/** How a schema key path fared against the declared config type: definitely
* present, definitely absent, or crossing a shape the walk cannot enumerate
* present, definitely absent, or crossing a type the walk cannot enumerate
* (only `missing` is a violation — `unknown` must never mis-report). */
type PathLookup = 'found' | 'missing' | 'unknown'
@@ -307,7 +307,7 @@ const PASSTHROUGH_WRAPPERS = new Set(['Partial', 'Required', 'Readonly', 'NonNul
/**
* Walk a schema key path against a declared type. This is a PRESENCE check,
* not a shape check: it answers "does the declared config type have a member
* not a runtime value check: it answers "does the declared config type have a member
* here", resolving interfaces (heritage included), type aliases, literals,
* intersections, unions, arrays, indexed access, pass-through utility
* wrappers, and type references across package-local and workspace imports.
@@ -412,7 +412,7 @@ function unwrapExpr(expr: ts.Expression): ts.Expression {
* Statically walk a schemastery schema expression to its key paths plus the
* packages whose schemas an intersect composes. A key path is the top-level
* key or a nested path through object/array compositions (`agents[].id`).
* Handles the shapes the repo declares — `z.object({…})` (possibly behind
* Handles the declaration forms the repo uses — `z.object({…})` (possibly behind
* chained calls) and `z.intersect([X.Config, …])` — and hard-errors on
* anything else, so a schema the walk cannot see fails the gate instead of
* silently thinning it. Nested values that are neither `object` nor `array`
@@ -521,7 +521,7 @@ function findSchemaExpr(ctx: FileCtx, pluginClass: ts.ClassDeclaration | null):
function findInject(ctx: FileCtx, pluginClass: ts.ClassDeclaration | null, violations: string[]): string[] {
const fromArray = (expr: ts.Expression, where: string): string[] => {
if (!ts.isArrayLiteralExpression(expr)) {
violations.push(`${where}: inject is not a plain string-array literal; teach the generator the new shape.`)
violations.push(`${where}: inject is not a plain string-array literal; teach the generator the new declaration form.`)
return []
}
return expr.elements.map(el => ts.isStringLiteral(el) ? el.text : el.getText(ctx.sf))
@@ -727,7 +727,7 @@ export function collectConfigCatalog(scanRoot: string = root): CatalogEntry[] {
}
// Fold composed schemas' key paths in, then check each path against the type.
// Only a definite miss fails; shapes the walk cannot enumerate stay unknown.
// Only a definite miss fails; types the walk cannot enumerate stay unknown.
const byName = new Map(entries.map(e => [e.pkg, e]))
for (const entry of entries) {
if (entry.kind !== 'config' || entry.schemaKeys === null || entry.schemaKeys === undefined) continue

View File

@@ -111,16 +111,16 @@ export const SERVICE_PAGE: Record<string, string> = {
*/
export const SERVICE_WALK_EXEMPTIONS: Record<string, string> = {
agent: 'not a service: the DX accessor field on Agent.ctx (root accessor defaulting to undefined) — docs/subsystems/core.md owns the Agent handle',
configuredAgentIdentities: 'not a service: launcher-provided boot-context value (ConfiguredAgentIdentities | undefined) — packages/core/agent-loop/README.md owns the launcher contract',
launcherSessionQueryPath: 'not a service: launcher-provided boot-context value (string | undefined) — packages/session-query/session-query-sqlite/README.md owns the launcher contract',
configuredAgentIdentities: 'not a service: launcher-provided boot-context value (ConfiguredAgentIdentities | undefined) — packages/core/agent-loop/README.md owns this launcher contract',
launcherSessionQueryPath: 'not a service: launcher-provided boot-context value (string | undefined) — packages/session-query/session-query-sqlite/README.md owns this launcher contract',
dshHomePath: 'not a service: boot-provided root accessor function (typeof dshHomePath | undefined) for Loader !!js config expressions — packages/boot/app-boot/README.md owns the boot contract',
headlessIo: 'not a service: launcher-provided root accessor value (HeadlessIo | undefined) for the headless bundle runner — packages/bundle/headless/README.md owns the launcher contract',
launcherEnvironment: 'not a service: launcher-provided root accessor value (EnvironmentSnapshot | undefined) — packages/util/environment/README.md owns the launcher contract',
headlessIo: 'not a service: launcher-provided root accessor value (HeadlessIo | undefined) for the headless bundle runner — packages/bundle/headless/README.md owns this launcher contract',
launcherEnvironment: 'not a service: launcher-provided root accessor value (EnvironmentSnapshot | undefined) — packages/util/environment/README.md owns this launcher contract',
lsp: 'interface-typed (LspService); implementing class Lsp is not the declared type name — packages/lsp/lsp/README.md owns the surface',
apiProxy: 'interface-typed (ApiProxy) with the class in api-proxy.ts, not index.ts — packages/host/apiproxy/README.md owns the surface',
appShell: 'client-side interface-typed browser service — packages/client/web/README.md owns the surface',
connection: 'client-side interface-typed browser service — packages/client/connection/README.md owns the surface',
chatFileMentions: 'client-side slot-contract accessor (ChatFileMentions) — packages/client/ui-conversation/README.md owns the surface',
chatFileMentions: 'client-side slot-contract accessor (ChatFileMentions) — packages/client/ui-conversation/README.md owns the API',
command: 'client-side interface-typed browser service — packages/client/ui-command/README.md owns the surface',
conversation: 'client-side interface-typed browser service — packages/client/ui-conversation/README.md owns the surface',
conversationEvents: 'client-side interface-typed registry — packages/client/runtime/README.md owns the surface',
@@ -483,13 +483,13 @@ export const TYPE_LINK_EXEMPTIONS: Readonly<Record<string, string>> = {
'z.core.ToJSONSchemaParams': 'zod projection parameters are owned by the zod v4 API',
TypeRTDisposer: 'TypeRT lifecycle contract is owned by packages/typert/type-meta/README.md',
InvokeRemoteRequest: 'gateway invocation contract is owned by packages/api/gateway/README.md',
LocaleDict: 'service-local dictionary shape is owned by packages/client/i18n/src/index.ts',
LocaleDict: 'service-local dictionary fields are 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',
WebUpgradeRoute:
'upgrade route registration contract is owned by packages/host/webserver/src/index.ts',
InvariantRegistration: 'service-local lifecycle handle is owned by packages/support/invariants/README.md',
KnobState: 'projection unit state shape is owned by packages/interaction/permission/README.md',
KnobState: 'projection unit state fields are owned by packages/interaction/permission/README.md',
PermissionSelect: 'permissions projection payload is owned by packages/interaction/permission/src/types.ts',
PromptAssembly: 'assembly result is owned by packages/core/system-prompt/README.md',
Sandbox: 'external E2B SDK handle is owned by packages/e2b/e2b/README.md',
@@ -752,7 +752,7 @@ export function maybeRecordPair(pageRel: string, before: Map<string, Buffer>, sc
// after review, never silently by regeneration.
return false
}
// The record must be exactly the well-formed two-entry shape for THIS pair;
// The record must contain exactly the two valid entries for THIS pair;
// a malformed or renamed-key sidecar is the pairing gate's problem to
// report, never something regeneration silently repairs into validity.
const recorded = parsePairMeta(meta)

View File

@@ -521,7 +521,7 @@ const SERVICE_ROLES: ServiceRole[] = [
mode: 'seam',
implementations: ['workflow-workerthread'],
consumers: ['tool-workflow', 'tool-ralph'],
note: 'One engine per context (bash shape, no named-provider registry); the general workflow and fixed Ralph consumers start runs whose agent() calls fan out through ctx.subagents.',
note: 'One engine per context, as in bash, with no named-provider registry; the general workflow and fixed Ralph consumers start runs whose agent() calls fan out through ctx.subagents.',
},
]
@@ -815,7 +815,7 @@ export class EventRelationCollector {
* Return every indexed call resolving to one local helper declaration.
* Fast path: when every same-file reference to the non-exported helper is
* provably a direct callee, module scoping confines all of its calls to that
* file, so only that file is indexed. Any other reference shape may alias
* file, so only that file is indexed. Any other reference form may alias
* the function value outward, so the original full package-source index
* decides instead.
*/
@@ -1155,7 +1155,7 @@ function renderEventRelations(pkgs: Pkg[], events: readonly EventEntry[]): strin
lines.push(`| \`${event.name}\` | \`${event.mode}\` | ${sourceLink(event.source)} | ${relationPackages(relation.dispatchers, pkgsByShort)} | ${listenerPackages(relation.listeners, pkgsByShort)} |`)
}
// Every declared event needs a dispatcher: zero means dead vocabulary or an
// unrecognized semantic dispatch shape. Listener-free extension points remain
// unrecognized semantic dispatch form. Listener-free extension points remain
// valid. Client-declared events are exempt: the relation scan seeds the HOST
// aggregate program only (host+client cannot share one program — the cordis
// Context merges collide), so client dispatch sites are structurally
@@ -1168,8 +1168,8 @@ function renderEventRelations(pkgs: Pkg[], events: readonly EventEntry[]): strin
if (undispatched.length > 0) {
throw new Error(
`event-producer-consumer matrix: no dispatcher found for declared event${undispatched.length > 1 ? 's' : ''} `
+ `${undispatched.map(name => `"${name}"`).join(', ')} — dead vocabulary, or a dispatch shape the semantic scan misses `
+ '(teach scripts/gen-doc-graphs.ts the shape)',
+ `${undispatched.map(name => `"${name}"`).join(', ')} — dead vocabulary, or a dispatch form the semantic scan misses `
+ '(teach scripts/gen-doc-graphs.ts that form)',
)
}
const declared = new Set(events.map(event => event.name))
@@ -1262,9 +1262,9 @@ function renderLifecycle(): string {
'',
'`dsh-compact-basic` uses `agent/pre-step` for pressure before request derivation and `agent/request-error` only for canonical context overflow. Once either trigger qualifies, optional tool-result pruning runs before summary selection. Recovery works between the closed failed step and failed turn close, and opens a fresh retry turn only when pruning or summarization advances the surface replacement generation; otherwise the original request error remains authoritative.',
'',
'The returned `agent/pre-step` decision is authoritative; listeners wrapping `next()` preserve downstream messages unless replacement is intentional. Steering and injected context pass through the same waterfall after a later boundary claims their next-step batch.',
'The returned `agent/pre-step` decision is authoritative; listeners wrapping `next()` preserve downstream messages unless replacement is intentional. Steering and injected context pass through the same waterfall after a later claim operation takes their next-step batch.',
'',
'SDK users that need replayable transcript data should consume `session/event`; `agent/*` is the live coordination surface for queue/status, prompt interception, request shaping, steering, continuation, and errors.',
'SDK users that need replayable transcript data should consume `session/event`; `agent/*` is the live coordination surface for queue/status, prompt interception, request construction, steering, continuation, and errors.',
'',
...maintenanceFooter(maintenance),
].join('\n')
@@ -1274,7 +1274,7 @@ function renderToolPipeline(): string {
const maintenance = 'curated Mermaid flow; exact tool schemas and event signatures live in generated catalogs'
return [
...generatedHeader('Tool Execution Pipeline'),
'This graph shows where policy, hooks, sandboxing, filesystem guards, result rewriting, final-outcome observation, and UI rendering fit without changing the loop. The transformable extension points are the `tools/pre-execute`, `tools/execute`, and `tools/post-execute` waterfalls; monotonic guards, definition-owned `finalizeContent`, and `tools/result` are the owner-enforced boundaries around them.',
'This graph shows where policy, hooks, sandboxing, filesystem guards, result rewriting, final-outcome observation, and UI rendering run without changing the loop. The `tools/pre-execute` waterfall runs first, monotonic guards run next, and the `tools/execute` and `tools/post-execute` waterfalls follow; the three waterfalls may transform a call. Definition-owned `finalizeContent` and `tools/result` run afterward.',
'',
'```mermaid',
'flowchart TD',
@@ -1380,7 +1380,7 @@ function renderIndex(docs: GraphDoc[]): string {
const maintenance = 'mixed: each linked page declares generated, hybrid, or curated mode'
return [
...generatedHeader('Documentation Graph Index'),
'These diagrams are the relationship layer above the generated catalogs. Use them to navigate package topology, capability seams, event flow, model-facing tools, app composition, and runtime lifecycle paths. Exact signatures and type shapes still live in the [subsystem pages](subsystems/core.md) (types + the generated `cordis-surface` regions) and [tool-catalog.md](tool-catalog.md).',
'These diagrams show relationships that the generated catalogs do not. Use them to find package relationships, capability seams, event flow, model-facing tools, app composition, and runtime lifecycle paths. Exact signatures and type definitions still live in the [subsystem pages](subsystems/core.md) (types + the generated `cordis-surface` regions) and [tool-catalog.md](tool-catalog.md).',
'',
'The process decision behind this index is recorded in [the documentation graph Agent Note](../.agents/notes/archived/process/2026-07-03-documentation-graph-atlas.md).',
'',

View File

@@ -139,7 +139,7 @@ describe('parseVendoredRows', () => {
expect(rows.every(row => /^https:\/\/\S+$/.test(row.upstream))).toBe(true)
})
it('yields nothing when the table shape changes, so the generator fails loud', () => {
it('yields nothing when the table columns change, so the generator fails loud', () => {
expect(parseVendoredRows('| `cordis/` | cordis | 4.0.0 | https://example.com | `abc123` |\n')).toEqual([])
})
@@ -215,7 +215,7 @@ describe('parsePyprojectRequirements', () => {
].join('\n'))).toEqual(['pydantic', 'tomli', 'pytest'])
})
it('accepts dependency-group includes and rejects unsupported requirement shapes', () => {
it('accepts dependency-group includes and rejects unsupported requirement forms', () => {
expect(parsePyprojectRequirements('[dependency-groups]\nbase = ["pytest"]\nall = [{ include-group = "base" }]\n'))
.toEqual(['pytest'])
expect(() => parsePyprojectRequirements('[project]\ndependencies = "pytest"\n')).toThrow(/must be an array/)

View File

@@ -475,7 +475,7 @@ function collectPythonRequirementArray(
}
}
/** Read an optional TOML table and reject a present value of another shape. */
/** Read an optional TOML table and reject a present non-table value. */
function optionalTomlTable(value: TomlValueWithoutBigInt | undefined, location: string): TomlTableWithoutBigInt | undefined {
if (value === undefined || isTomlTable(value)) return value
throw new Error(`gen-third-party-notices: ${location} must be a table.`)
@@ -487,7 +487,7 @@ function optionalTomlTable(value: TomlValueWithoutBigInt | undefined, location:
* `[build-system]`, `dependencies` under `[project]`, and every key under
* `[project.optional-dependencies]` and `[dependency-groups]`. A TOML parser
* owns comments, quoted keys, escapes, and array boundaries; unsupported
* requirement shapes fail instead of disappearing from the notices.
* requirement forms fail instead of disappearing from the notices.
* @param text - the complete `pyproject.toml` contents.
* @returns the local project name and declared requirement names.
*/

View File

@@ -7,7 +7,7 @@
* the narrowest safe granularity — code-fence-only splice, changed
* Markdown units, heading sections, whole document — and `--apply` writes
* the computed counterpart for pairs whose change is code-fence-only.
* The briefing contract lives in `scripts/translation-brief.ts`; the
* The briefing rules live in `scripts/translation-brief.ts`; the
* consuming workflow is `.agents/skills/dsh-translate-docs/SKILL.md`.
*/

View File

@@ -15,7 +15,7 @@ interface Profile {
// A one-time audit against eslint.config.mjs blob 696b08282885296830189fdafe7051a356806fc2
// mapped @typescript-eslint/* to typescript/* and four extension rules to their
// Oxlint core equivalents. These fingerprints pin the resulting repository
// contract; they do not re-evaluate that deleted baseline or track its preset.
// snapshot; they do not re-evaluate that deleted baseline or track its preset.
const profiles = {
source: {
count: 88,
@@ -84,7 +84,7 @@ describe('Oxlint repository rule fingerprint', () => {
}
const overrides: readonly unknown[] = parsed.overrides
it('pins the complete override shape', () => {
it('pins every override field', () => {
expect(overrides).toHaveLength(8)
})

View File

@@ -19,7 +19,7 @@ interface PackageManifest {
devDependencies?: Record<string, string>
}
/** One package and the files participating in its invariant publication contract. */
/** One package and the files participating in its invariant publication rules. */
export interface PackageInvariantOwner {
readonly dir: string
readonly manifestPath: string
@@ -53,7 +53,7 @@ export function packageInvariantOwners(root: string): PackageInvariantOwner[] {
})
}
/** Return all violations of the package-invariant companion contract. */
/** Return all violations of the package-invariant companion rules. */
export function collectPackageInvariantViolations(root: string): PackageInvariantViolation[] {
const violations: PackageInvariantViolation[] = []
for (const owner of packageInvariantOwners(root)) {

View File

@@ -341,7 +341,7 @@ function nodeCompatSmokeGates(options: { cliSmoke?: boolean } = {}): Gate[] {
return gates
}
/** Active Node major used to scope version-specific compatibility contracts. */
/** Active Node major used to select version-specific compatibility checks. */
function runningNodeMajor(): number {
const major = Number.parseInt(process.versions.node.split('.')[0] ?? '', 10)
if (!Number.isSafeInteger(major)) {
@@ -473,7 +473,7 @@ function lintGate(options: { needs?: string[] } = {}): Gate {
// The heavy suites run uninstrumented beside the thresholded gate: their
// compiler- and subprocess-bound fixtures pay a multiple of their runtime
// under v8 instrumentation while contributing nothing the thresholds need
// (membership contract in scripts/coverage-exempt.ts).
// (membership rules in scripts/coverage-exempt.ts).
//
// DSH_COVERAGE_MAX_WORKERS is the lane's worker budget, so the two parallel
// gates split it instead of each claiming it whole (the failover pool's

File diff suppressed because one or more lines are too long

View File

@@ -137,7 +137,7 @@ describe('global test invariant host', () => {
.toEqual(Object.keys(testInvariantCompanions).sort())
})
it('loads and executes every source companion through the real Loader shape', async () => {
it('loads and executes every source companion through the real Loader setup', async () => {
const owners = new Map(packageInvariantOwners(process.cwd()).map(owner => [owner.sourcePath, owner.packageName]))
const registrations = new Map<string, string>()
const loader = Object.create(Loader.prototype) as Loader

View File

@@ -24,7 +24,7 @@ declare global {
}
}
/** Loader-safe shape shared by every package invariant companion. */
/** Loader-safe exports shared by every package invariant companion. */
export interface TestInvariantCompanion {
readonly name: string
readonly inject: readonly string[]

View File

@@ -54,7 +54,7 @@ export interface GitIndexBlob {
* @param root - Repository root.
* @param path - Repository-relative path.
* @returns The stage-zero blob, or `undefined` when the path is absent.
* @throws Error when the path is unmerged or has an invalid index shape.
* @throws Error when the path is unmerged or its index entries are not a valid merge state.
*/
export function readGitIndexBlob(root: string, path: string): GitIndexBlob | undefined {
const output = runGit(

View File

@@ -80,7 +80,7 @@ const PAIR_META_LINE = /^([^:#]+\.md): ([0-9a-f]{40})$/
/**
* Parse a `foo.i18n.yaml` consistency record into basename → recorded blob
* hash, or undefined when any non-comment line deviates from the exact
* `<basename>.md: <40-hex>` shape or repeats a key. Consumers must
* `<basename>.md: <40-hex>` format or repeats a key. Consumers must
* additionally require exactly the two expected basenames — a renamed key is
* a malformed record, never a silently-missing entry.
* @param content - Sidecar file text.
@@ -118,7 +118,7 @@ export function renderPairMeta(source: string, sourceHash: string, zh: string, z
].join('\n')
}
/** Validated shape of `scripts/translation-pairing.manifest.json`. */
/** Validated fields of `scripts/translation-pairing.manifest.json`. */
export interface TranslationPairingManifest {
/** Source documents exempt from pairing because they are generated, instructional, or bilingual by construction. */
excluded: string[]

View File

@@ -21,7 +21,7 @@ const retainedExamples = [
['### Stiff passive voice → Active and natural', 'a green gate means the pair was confirmed consistent at these exact contents, not that the confirmation was sound.', '门禁通过意味着这组文档在当前内容上的一致性得到了确认,不代表确认本身正确可靠。'],
['### Invented word → Natural expression', 'A sidecar record of both blob hashes makes consistency checkable', '伴随记录保存两侧 blob hash使一致性可检查'],
['### Em-dash → Colon/period', 'FIXME — an issue that should block a new release.', 'FIXME应当阻塞新版本发布的问题。'],
['### Overly literal → Meaningful rendering', 'awkward phrasing is easier to hear without the source anchoring you', '不对照原文时,更容易察觉别扭的表达'],
['### Overly literal → Meaningful rendering', 'awkward phrasing is easier to notice when you read the translation without comparing it with the source', '不对照原文阅读译文时,更容易察觉别扭的表达'],
['### Terminology — do not translate what should be kept in English', 'typed service seams, and explicit extension points', '类型化的服务 seam 与显式扩展点'],
['### Slang/jargon → Professional phrasing', 'The committed agent workflow lives in .agents/skills/dsh-translate-docs', '仓库内置的 agent 工作流见 .agents/skills/dsh-translate-docs'],
['### "For humans" — translate the intent, not the word', 'For humans, start with the development guide', '面向开发者:请先阅读开发指南'],
@@ -44,7 +44,7 @@ describe('translation prompt rendering', () => {
expect(zh).toContain('from Chinese to English')
})
it('retains every v4 embedded example', () => {
it('contains every embedded example', () => {
for (const example of retainedExamples) {
for (const fragment of example) expect(document).toContain(fragment)
}

View File

@@ -169,7 +169,7 @@ function unescapeResponseBody(value: string): string {
}).join('\n')
}
/** Serialize a response in the exact escaped three-section shape the prompt requests. */
/** Serialize a response in the exact escaped three-section format the prompt requests. */
export function renderTranslationResponse(response: TranslationResponse): string {
return RESPONSE_SECTIONS.map(section => `<${section}>\n${escapeResponseBody(response[section])}\n</${section}>`).join('\n\n')
}
@@ -178,7 +178,7 @@ export function renderTranslationResponse(response: TranslationResponse): string
* Parse the three-section response. Sections must each appear exactly once
* and in order; escaped delimiter lines in Markdown bodies are restored.
* A fenced ```xml wrapper around the whole response is tolerated, matching
* the shape some models echo back from the prompt's own example.
* the wrapper some models copy from the prompt's own example.
*/
export function parseTranslationResponse(text: string): TranslationResponse {
let body = text.trim()

View File

@@ -1,6 +1,6 @@
/**
* Enforce Agent Note lifecycle/class paths and dated filenames. Structural rules
* are shared with `agent-note-tree.ts`; the closed classification contract lives
* are shared with `agent-note-tree.ts`; the closed classification rules live
* in `.agents/notes/README.md`.
*/

View File

@@ -9,7 +9,7 @@ import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { agentNoteRoot, walkAgentNoteTree } from './agent-note-tree.ts'
/** The date the format contract landed; the grandfather comment is valid only before it. */
/** The date these format rules took effect; the grandfather comment is valid only before it. */
const FORMAT_ADOPTED = '2026-07-05'
/** The exact comment a pre-format Agent Note carries in place of `## Alternatives considered`. */

View File

@@ -99,7 +99,7 @@ if (!writeMode) {
}
if (errors.length > 0) {
console.error('verify-archived-agent-notes: archive contract violated:')
console.error('verify-archived-agent-notes: archive rules violated:')
for (const error of errors) console.error(` ${error}`)
process.exit(1)
}

View File

@@ -19,7 +19,7 @@ const SHIPPED_CONFIG_GLOBS = [
'python/*/src/**/cordis.yml',
]
/** Ordinary single-line forms this narrow source-shape check rejects; not full YAML analysis. */
/** Ordinary single-line configuration forms this source check rejects; not full YAML analysis. */
const INLINE_DENY = /^\s*(apiKey|baseURL|apiKeyEnv|authToken|headers)\s*:\s*!!js\b/
/** Return every forbidden inline environment form in shipped configuration. */

View File

@@ -75,9 +75,9 @@ function unwrapExpression(e: ts.Expression): ts.Expression {
/**
* Classify inline callable annotations. Mixed callable literals fail closed;
* other annotations are ordinary value shapes.
* other annotations are ordinary value types.
* @param type - the declarator's type annotation.
* @returns the signature to check, 'refuse' for an unclassifiable callable literal, or null for a non-callable shape.
* @returns the signature to check, 'refuse' for an unclassifiable callable literal, or null for a non-callable type.
*/
function callableAnnotation(type: ts.TypeNode): ts.SignatureDeclarationBase | 'refuse' | null {
if (ts.isFunctionTypeNode(type)) return type
@@ -446,7 +446,7 @@ function checkScope(
if (ts.isExportAssignment(stmt)) {
if (stmt.isExportEquals) {
// `export =` has no ESM consumer surface in this repo and the walk
// cannot classify its operand's shape; refuse rather than fail open.
// cannot classify its operand's type; refuse rather than fail open.
w.violations.push(`export-equals assignment (${pointer(w.rel, w.sf, stmt)}) is not a gate-supported export form; use ESM named exports.`)
continue
}

View File

@@ -1,4 +1,4 @@
/** Verify package-owned invariant source and publication contracts. */
/** Verify package-owned invariant source and publication rules. */
import { resolve } from 'node:path'
import {

View File

@@ -217,12 +217,12 @@ function validateNestedVerbatim(raw: readonly string[], fragments: Set<string>):
return { blocks }
}
/** GitHub-style fragment for the simple ASCII nested titles allowed by this contract. */
/** GitHub-style fragment for the simple ASCII nested titles allowed by these rules. */
function headingFragment(title: string): string {
return title.toLowerCase().replaceAll('`', '').replaceAll(/[^a-z0-9 _-]/g, '').trim().replaceAll(/\s+/g, '-')
}
/** A direct stable system-prompt contribution, as named by the README contract. */
/** A direct stable system-prompt contribution, as named by the README rules. */
function isDirectSystemPromptSurface(title: string): boolean {
return /\bsystem prompt\b/i.test(title)
}

View File

@@ -291,6 +291,6 @@ if (errors.length === 0) {
process.exit(0)
}
console.error('verify-translation-pairing: bilingual pairing contract violated (see docs/i18n/README.md):')
console.error('verify-translation-pairing: bilingual pairing rules violated (see docs/i18n/README.md):')
for (const message of errors) console.error(` ${message}`)
process.exit(1)