docs: make technical prose concrete
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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>>
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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).',
|
||||
'',
|
||||
|
||||
@@ -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/)
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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`.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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`.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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`. */
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user