refactor: replace overloaded surface terminology

This commit is contained in:
Turtle
2026-07-24 19:54:25 +08:00
parent c172faed37
commit 0c708cb10d
626 changed files with 1396 additions and 1397 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-06-20-core-data-structures-catalog.md
2026-06-20-core-data-structures-catalog.md: 957d3a31cf690b3f0fb821b69bbc3d6d5005b1d7
2026-06-20-core-data-structures-catalog.md: b793b65c7cd55a4b0fe7de97fcd8e43f7056d2ea
2026-06-20-core-data-structures-catalog.zh.md: aec1489695f8400768c958426a9d6a8d4061db0c

View File

@@ -40,7 +40,7 @@ The durability requirement was specific: the doc shows the **literal** current t
### Maintenance is the author's job, with a gate backstop
`verify-type-equiv` catches a *drifted paste* of an already-documented type, but it cannot tell you a brand-new core type went undocumented. So AGENTS.md and the `dsh-code-review` skill were updated to require keeping the catalog in sync when a change adds or reshapes a documented type — the gate handles drift, the human handles new surface.
`verify-type-equiv` catches a *drifted paste* of an already-documented type, but it cannot tell you a brand-new core type went undocumented. So AGENTS.md and the `dsh-code-review` skill were updated to require keeping the catalog in sync when a change adds or reshapes a documented type — the gate handles drift, the human handles new types.
## Alternatives considered

View File

@@ -1,6 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-06-export-surface-jsdoc-gate.md
2026-07-06-export-surface-jsdoc-gate.md: 821f68ebe60eba44cade223b3bc8286e09740956
2026-07-06-export-surface-jsdoc-gate.zh.md: ec5bf67ccbfe9fcc1996aa47177c2d9b1145cd67
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-06-export-jsdoc-gate.md
2026-07-06-export-jsdoc-gate.md: 5f594cf279c07c41a96a124f1d25dbf880543718
2026-07-06-export-jsdoc-gate.zh.md: 9d76fc494498424471c725dae68abca833ef9c45

View File

@@ -1,8 +1,8 @@
# Agent Note: Export-surface JSDoc gate
# Agent Note: Export JSDoc gate
Status: implemented
English | [中文](2026-07-06-export-surface-jsdoc-gate.zh.md)
English | [中文](2026-07-06-export-jsdoc-gate.zh.md)
## Problem
@@ -15,7 +15,7 @@ A new gate, `scripts/verify-export-jsdoc.ts` (`pnpm run verify-export-jsdoc`, wi
The contract by declaration kind:
- Every exported name needs JSDoc with non-empty description prose.
- Function-like exports (function declarations; consts with function initializers or an INLINE callable annotation; non-identifier function default exports) follow the full function contract, with wrapper expressions (parentheses, `as`/`satisfies` casts, non-null assertions) peeled before classifying. A const whose declarator is annotated with a NAMED type (`export const f: Handler = …`) defers the signature contract to that type's own declaration and `@returns` stays optional; an inline `(x: T) => U` annotation or single-call-signature literal is the surface signature itself and gets the full contract, and a literal mixing call/construct signatures with anything else is refused outright (no single signature to hold the tags against — extract a named type).
- Function-like exports (function declarations; consts with function initializers or an INLINE callable annotation; non-identifier function default exports) follow the full function contract, with wrapper expressions (parentheses, `as`/`satisfies` casts, non-null assertions) peeled before classifying. A const whose declarator is annotated with a NAMED type (`export const f: Handler = …`) defers the signature contract to that type's own declaration and `@returns` stays optional; an inline `(x: T) => U` annotation or single-call-signature literal is the exported signature itself and gets the full contract, and a literal mixing call/construct signatures with anything else is refused outright (no single signature to hold the tags against — extract a named type).
- Exported classes need class-level prose; public methods (statics included — reachable on the exported name) follow the function contract; public properties and accessors need prose (a get/set pair is covered by the getter). Overload implementations are exempt — the signatures carry the docs.
- Exported interfaces, type aliases, and enums need prose on the declaration; member-level enforcement is deliberately deferred (the highest-value member surface — seam service classes — is already under the cordis gate).
- Exported namespaces recurse (inside an ambient `declare` namespace every member exports implicitly); the namespace itself needs prose only when it does not merge with a documented same-name declaration (the Config-namespace idiom documents the plugin once).
@@ -24,7 +24,7 @@ The contract by declaration kind:
Three exemption families keep the gate from demanding boilerplate, in the spirit of the cordis gate's `this`/`next` exemptions (documenting an exempt name anyway is allowed; only absence goes unchecked):
- **Heritage members.** Overrides inherit documentation from their base declaration. New public surface still requires docs: added parameters, a public override of a protected member, or a concrete return over a void base. Heritage lookup and inferred return classification are the gate's only type-checker work; other checks use the AST.
- **Heritage members.** Overrides inherit documentation from their base declaration. New public API still requires docs: added parameters, a public override of a protected member, or a concrete return over a void base. Heritage lookup and inferred return classification are the gate's only type-checker work; other checks use the AST.
- **Plugin-protocol slots.** Top-level `name` / `inject` / `reusable` / `Config` consts and the `apply` entry, plus the same slots as statics on a plugin class, are framework protocol: their shape is fixed by cordis, and the module doc comment plus the `interface Config` carry the plugin's real semantics.
- **Constructors**, mirroring the cordis gate: plugin classes are framework-constructed, and the class doc owns the story.
@@ -33,8 +33,8 @@ Three exemption families keep the gate from demanding boilerplate, in the spirit
## Alternatives considered
- **eslint-plugin-jsdoc** (`require-jsdoc`/`require-param`/`require-returns`) — covers the mechanical core but cannot express the repo's contract: the heritage-member exemption needs cross-package type resolution, the protocol-slot and namespace-merge idioms are cordis-specific, and the completeness semantics (prose-above-tags, stale-tag errors, aggregate reporting) already have one home in `scripts/jsdoc.ts` shared with the catalog generator. Two subtly different definitions of "documented" is the failure mode this repo's one-home rule exists to prevent.
- **Extending `gen-cordis-catalog.ts`** — the catalog generator renders a curated surface and gates its freshness; a repo-wide walk has no catalog to render. Sharing the helpers while keeping the walks separate keeps each gate's scope legible.
- **Enforcing interface/type-alias member docs** — deferred: it would multiply the checked surface for members that are largely self-describing fields, while the seam classes carrying the load-bearing member contracts are already gated. Revisit if member-doc drift shows up in review.
- **Extending `gen-cordis-catalog.ts`** — the catalog generator renders a curated API and gates its freshness; a repo-wide walk has no catalog to render. Sharing the helpers while keeping the walks separate keeps each gate's scope legible.
- **Enforcing interface/type-alias member docs** — deferred: it would multiply the checked scope for members that are largely self-describing fields, while the seam classes carrying the load-bearing member contracts are already gated. Revisit if member-doc drift shows up in review.
## Consequences

View File

@@ -2,7 +2,7 @@
Status: implemented
[English](2026-07-06-export-surface-jsdoc-gate.md) | 中文
[English](2026-07-06-export-jsdoc-gate.md) | 中文
## 问题

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-06-node-engine-floor.md
2026-07-06-node-engine-floor.md: ad21fbfe034cbf4bb7b75aaac4113f3139a1832d
2026-07-06-node-engine-floor.md: 4d24a861bfa1a27b5aa4e07da1ed21452c7be566
2026-07-06-node-engine-floor.zh.md: e2ef7a99a8c3045b00f4980953f0adbe4a788cfb

View File

@@ -19,7 +19,7 @@ Two Node features gate the source runtime:
Those source features clear on the 22.x line at **22.18**, but the installed Pi adapter dependency raises the advertised LTS floor. `@deepseek-ai/dsh-llm-pi-ai` depends on `@earendil-works/pi-ai@0.79.3`, whose package declares `engines.node >=22.19.0`, so the LTS floor is **22.19**. The 24.x branch remains `>=24.0.0`. The disjoint range excludes Node 23 entirely: Node 23.023.5 still has at least one flagged source feature, and the 23 line is non-LTS/EOL, so advertising `>=23.6` would add a dead release line and a CI leg no deployment should use.
`@types/node` remains pinned to the 22.x line (`^22.20.0`) to match the LTS support line: reaching for a Node 23+/24+/25+ API fails `tsc` on every machine and in the typecheck gate, rather than compiling clean and surviving to a runtime failure only a floor matrix leg could catch. The whole tree typechecks clean against the Node 22 type surface today, so the pin costs nothing.
`@types/node` remains pinned to the 22.x line (`^22.20.0`) to match the LTS support line: reaching for a Node 23+/24+/25+ API fails `tsc` on every machine and in the typecheck gate, rather than compiling clean and surviving to a runtime failure only a floor matrix leg could catch. The whole tree typechecks clean against the Node 22 type API today, so the pin costs nothing.
## Consequences

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-12-package-model-experience-contract.md
2026-07-12-package-model-experience-contract.md: 92a8e5a1a81d00dae085e4af89456896373058e6
2026-07-12-package-model-experience-contract.md: 8462cc20e8de43927cd04b73cfdb11a0c3d77336
2026-07-12-package-model-experience-contract.zh.md: ded8c9fd940b986d9b37ad1563060b8b96e966bb

View File

@@ -12,7 +12,7 @@ A package README can explain APIs and runtime mechanics without answering the qu
Every workspace package README with a model-facing or model-adjacent contract ends with the canonical [Model Experience section](../../../../docs/cookbook/adding-a-package.md#4-write-the-package-readme), immediately before `## Known Limitations and Deferred Work`; a package on the no-limitations allowlist ends with Model Experience itself. An audited model-agnostic generic package omits the section through `NO_MODEL_EXPERIENCE_SECTION`.
Packages with direct, conditional, capped, lifetime, multi-surface, or auxiliary-model effects use one H3 per context surface. Each surface contains three ordered H4 fields—`What the model sees`, `Token effect`, and `KV Cache effect`—and each field starts with one prose paragraph. The cache field distinguishes append-only growth, a stable repeated prefix, replacement of earlier tokens, and an independent model request; it names every package-owned configuration, scope, lifecycle, compaction, or routing change that can alter the request before newly appended content. “Does not invalidate” means the package preserves an already-reusable prefix, not that a provider promises a cache hit or retention period. Stable package-owned text is quoted exactly: system-prompt prose and other long literals use a titled H5 plus `markdown` fence under the field that introduces them, normally `What the model sees`, while short literals stay inline with named interpolation placeholders. Tool-schema surfaces link their anchored section in the generated [tool catalog](../../../../docs/tool-catalog.md) and state only composition or configuration deltas; runtime-only definitions explain why the catalog omits them. Data-dependent and provider-owned text is summarized. Agent-scoped visibility is explicit, and prompt and schema surfaces remain separate when scoping can hide one without the other.
Packages with direct, conditional, capped, lifetime, multi-surface, or auxiliary-model effects use one H3 per context surface. Each surface contains three ordered H4 fields—`What the model sees`, `Token effect`, and `KV Cache effect`—and each field starts with one prose paragraph. The cache field distinguishes append-only growth, a stable repeated prefix, replacement of earlier tokens, and an independent model request; it names every package-owned configuration, scope, lifecycle, compaction, or routing change that can alter the request before newly appended content. “Does not invalidate” means the package preserves an already-reusable prefix, not that a provider promises a cache hit or retention period. Stable package-owned text is quoted exactly: system-prompt prose and other long literals use a titled H5 plus `markdown` fence under the field that introduces them, normally `What the model sees`, while short literals stay inline with named interpolation placeholders. Tool-schemas link their anchored section in the generated [tool catalog](../../../../docs/tool-catalog.md) and state only composition or configuration deltas; runtime-only definitions explain why the catalog omits them. Data-dependent and provider-owned text is summarized. Agent-scoped visibility is explicit, and prompt and schemas remain separate when scoping can hide one without the other.
A package with no model-context effect, or one path rendered entirely by another package, uses the verifier's audited short form: one sentence beginning `None, as ` or `Indirectly, through ` followed by a `KV Cache effect` H4 and one prose paragraph. Pure transport and keyless test-support packages use the none form when they create no model-bound content. Provider backends use the indirect form even when they cap or filter data, and wiring bundles use it when named children own every effect. These sections locate the contribution and disclaim direct cache invalidation without restating the consumer. Structured sections likewise document only package-owned inputs, transformations, and deltas.
@@ -21,7 +21,7 @@ A package with no model-context effect, or one path rendered entirely by another
## Alternatives considered
- **Document only packages that register prompts or tools** — rejected because backends, policy plugins, adapters, persistence, scoping, and compaction change the content or lifetime of tokens without owning a model-facing schema.
- **Generate one central context-cost catalog from source** — rejected because an AST can find registrations but cannot infer semantic conditions such as history retention, output truncation, parent-versus-child visibility, or an auxiliary model boundary. The package README is the implementation-local contract; a central copy would add another drift surface.
- **Generate one central context-cost catalog from source** — rejected because an AST can find registrations but cannot infer semantic conditions such as history retention, output truncation, parent-versus-child visibility, or an auxiliary model boundary. The package README is the implementation-local contract; a central copy would add another drift point.
- **Require numeric token counts** — rejected because exact counts depend on the selected model tokenizer, adapter serialization, configuration, and runtime data. The stable contract is the growth shape: fixed per request, conditional per call, retained, replaced, capped, or zero-direct.
- **Use a table** — rejected because exact source text and conditional result shapes make cells dense and difficult to scan. Repeated subsections give each context surface readable vertical space while preserving the same fields.
- **Allow every zero-impact package to omit the section** — rejected because unconstrained absence is ambiguous between an audited zero and forgotten documentation. Omission is reserved for model-agnostic generic packages named with a reason in the verifier; model-adjacent zero-impact packages keep one explicit sentence.
@@ -30,4 +30,4 @@ A package with no model-context effect, or one path rendered entirely by another
## Consequences
A reviewer can start at any model-facing or model-adjacent package and see its contribution to the conversation model, child models, and auxiliary calls without reconstructing the full plugin graph. Token-budget work can distinguish repeated request overhead from data-dependent history, while cache-sensitive work can identify append-only paths and the earliest package-owned prefix mutation. Agent-scoped changes have an explicit documentation checkpoint. Package authors maintain one or more compact context-surface blocks or one classified short form whenever model-visible behavior changes; audited generic packages carry no irrelevant model boilerplate. The structured fields do not promise provider-exact token counts or cache hits; measurements remain model-, provider-, and workload-specific, while the documented growth, visibility, and prefix-stability contract stays stable.
A reviewer can start at any model-facing or model-adjacent package and see its contribution to the conversation model, child models, and auxiliary calls without reconstructing the full plugin graph. Token-budget work can distinguish repeated request overhead from data-dependent history, while cache-sensitive work can identify append-only paths and the earliest package-owned prefix mutation. Agent-scoped changes have an explicit documentation checkpoint. Package authors maintain one or more compact context-entry blocks or one classified short form whenever model-visible behavior changes; audited generic packages carry no irrelevant model boilerplate. The structured fields do not promise provider-exact token counts or cache hits; measurements remain model-, provider-, and workload-specific, while the documented growth, visibility, and prefix-stability contract stays stable.

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-19-remove-generated-agent-note-index.md
2026-07-19-remove-generated-agent-note-index.md: 652ac72afe69284240667e61af1f3fbfcb182ddb
2026-07-19-remove-generated-agent-note-index.md: 60dba14064ffe294228968cdb111920696fe7d63
2026-07-19-remove-generated-agent-note-index.zh.md: 6e1967fbde0c6ac59bbc3a184dad68c989efadbc

View File

@@ -8,7 +8,7 @@ English | [中文](2026-07-19-remove-generated-agent-note-index.zh.md)
A committed Agent Note index duplicates facts already encoded by each file's lifecycle/class path, filename date, and H1. Every branch that adds, moves, or renames an otherwise unrelated Agent Note rewrites the same generated file, making that artifact a predictable merge hotspot.
The centralized chronological list adds little discovery value beyond browsing the lifecycle/class tree or searching the repository, while its generator, renderer, command, and freshness check remain maintenance surface.
The centralized chronological list adds little discovery value beyond browsing the lifecycle/class tree or searching the repository, while its generator, renderer, command, and freshness check remain maintenance burden.
## Decision

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-03-package-anchored-subsystem-pages.md
2026-08-03-package-anchored-subsystem-pages.md: 2a47f35e9d3755286bed7d42f59fd21e30f9148d
2026-08-03-package-anchored-subsystem-pages.md: 40f330d0feaca519bdc683e1992597b4be46cd8e
2026-08-03-package-anchored-subsystem-pages.zh.md: 53216a430b979f0612f256aaec9774b88fe14bbd

View File

@@ -20,7 +20,7 @@ The [subsystems README](../../../../docs/subsystems/README.md) indexes every pag
## Alternatives considered
**Keep the spine-vs-subsystem scoping rule.** It answered "is this type core?" per type, which is why the front page accumulated types from four packages while missing half of `packages/core/agent`'s public surface. Predictability by repository layout won.
**Keep the spine-vs-subsystem scoping rule.** It answered "is this type core?" per type, which is why the front page accumulated types from four packages while missing half of `packages/core/agent`'s public API. Predictability by repository layout won.
**A flat single-document catalog.** Already rejected in the [original catalog note](2026-06-20-core-data-structures-catalog.md); the growth to forty-one pages confirmed that verdict.