Commit Graph
37 Commits
Author SHA1 Message Date
pku-xht 8d3674695b docs(i18n): localize Chinese internal links 2026-08-18 19:00:37 +08:00
Tianyi Cui a2d0f7f411 refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
2026-08-13 00:54:38 +08:00
xjt 0a8c9fb1f9 docs(i18n): address final proofreading feedback 2026-08-12 16:43:38 +08:00
xjt 4806d94715 docs(i18n): include complete proofreading corpus 2026-08-12 12:30:19 +08:00
Tianyi Cui 25dcd7293c docs: purge chain-of-thought leakage from prose
Delete design-session citations (decision/audit/plan ordinals, stack
positions), change narration, review choreography, and reviewer-addressed
justification from comments, JSDoc, docs, READMEs, Agent Notes, tests, and
generator templates; restate every affected fact as current-state contract
prose. Fix generated docs at their sources and regenerate the catalogs and
cordis-surface regions; re-paste type-equiv blocks; update every bilingual
counterpart and re-record the pairs. Record the citation rule in the
committed-artifact-citations Agent Note.
2026-08-09 21:10:59 +08:00
Turtle dda02250f5 docs: reserve seam for complete capabilities 2026-08-09 17:26:57 +08:00
xjt a7af54a8d3 docs(i18n): standardize contract terminology 2026-08-09 11:33:14 +08:00
Tianyi Cui ba3125234a docs: rename core-data-structures/ to subsystems/
The folder is becoming the home of one-doc-per-subsystem pages (intro +
data structures + cordis services/events), so the name must describe the
whole contract, not just the type-vocabulary third of it. Mechanical
rename rebuilt on current master: every inbound Markdown link, generator
constant, website route, type-equiv manifest path, and spec expectation
moves together; the zh sides of the notes whose prose names the folder
are aligned (子系统) in the same change; touched bilingual pairs
re-recorded; translation-prompt snapshot re-recorded (its example embeds
development.md). Historical Agent Note slugs keep their dated
filenames.
2026-08-09 01:27:09 +08:00
Chinesezjc eb3b635796 docs(tools): widen the ungated language-prose list and correct three JSDoc claims 2026-08-06 01:38:26 +08:00
Chinesezjc 21641ae316 docs(tools): widen the no-runtime reachable set in resolveFlavor 2026-08-06 01:16:09 +08:00
Chinesezjc 24cfe8f777 docs(code-runtime): name python in the reference page and complete the ungated-edit list 2026-08-06 00:22:05 +08:00
Chinesezjc b2c1872799 docs(tools): cite per-character Unicode ages and the ungated seam edit 2026-08-06 00:07:10 +08:00
Chinesezjc 05426906b0 docs(tools): count the union member as an edit, and re-scope the runtime guards
The 'adding a language is two table entries plus its renderer' checklist
predates the `CodeSdkLanguage` union and now contradicts the mechanism
sentence beside it: following it literally leaves the union untouched, which
is exactly the excess-property error that sentence promises. It is three
parallel edits, in the note's Decision and Consequences and in the
`SDK_RENDERERS` JSDoc.

Two guard descriptions still claimed work the compiler took over. The
Decision's 'the drift this guards against' now names the `satisfies` pins and
leaves the guards their reachable case, a mounted runtime reporting a language
neither table knows; `resolveFlavor`'s JSDoc drops 'keeps the table coupled to
SDK_RENDERERS' for the same reason. The Consequences said a half-added
language 'cannot arise' for the runtime guards — it can, one PR later at the
consumer's integration point, and never on this base; the claim is now about
timing rather than impossibility.
2026-08-05 23:44:26 +08:00
Chinesezjc e14bcfb08a refactor(tools): pin the two language tables to one union, and name python at the seam
`SDK_RENDERERS` and `RUN_CODE_FLAVORS` had to stay in step by review alone:
the `Object.hasOwn` guards catch drift only once a runtime reporting the
half-added language exists, which is the one case that cannot arise. Both
tables are now `satisfies`-checked against a shared `CodeSdkLanguage` union,
so a missing or extra entry fails `typecheck`. The declared `Record<string, …>`
type stays, since `CodeRuntime.language` is an unconstrained `string`.

The code-runtime seam's own README row and `CodeRuntime.language` JSDoc still
named `'typescript'` as the sole well-known value; both now name `'python'`
too and say only `'typescript'` has a published backend.
2026-08-05 23:25:42 +08:00
Chinesezjc 7d957bc799 docs(tools): name both raw routes, complete the evaluation-floor list
The previous commit's `UNPRINTABLE` sentence said the raw-reach point for all
three characters is `pyScalar`'s `JSON.stringify`, and the test comment said
that route is the only one. Both are exclusive claims and both are false: the
subscript tool-name comment calls `JSON.stringify` itself, and a tool name
carrying NEL, LS, or PS always lands there, none of the three being
`XID_Continue`. `pyScalar`'s own docstring already recorded that inheritance,
so the file contradicted itself. Both sentences now name the two call sites.

The note's evaluation axis was introduced as "the `typing` names the block
spells", which excludes one of its own members (`A | B` is operator syntax)
and omitted PEP 585 builtin generics — `dict[str, Any]` and `list[…]` appear
in nearly every render and need 3.9. The axis is now "the names and syntax the
block would evaluate at definition time", enumerated 3.8 through 3.11.

The test title covered two of the three characters it asserts; NEL is NEXT
LINE, neither a line nor a paragraph separator.
2026-08-05 22:56:32 +08:00
Chinesezjc b869a3b078 docs(tools): close the NEL half of the raw pass-through and reflow
Four non-blocking review suggestions, all prose plus one assertion.

`UNPRINTABLE`'s new sentence named three characters but only two raw-reach
points, leaving "and NEL?" open; it now says all three reach text through
`pyScalar`, and how the description path handles each. `pyScalar`'s
raw-pass-through list already covered NEL under "the C1 controls", and the
test now pins it alongside LS and PS, so the docstring's claim has a
mechanical check for every character it names.

The test title said "paragraph separators" for a pair whose first member is
LINE SEPARATOR. Two docstring paragraphs are reflowed to the file's ~80
columns after the earlier inserts left short lines.

The note's CPython-floor obligation gains a second axis: the `typing` names
the block spells (`TypedDict` 3.8, `NotRequired` 3.11, `A | B` annotations
3.10) are definition-time evaluation floors, not parse floors, so the floor PR
does not read "parseable on the supported range" as "executable on it".
2026-08-05 22:43:42 +08:00
Chinesezjc 0891556cb4 docs(tools): qualify the three remaining mode-dependent only-claims
The `mode: 'code'` qualification landed on the module header and
`isBareIdentifier` but not on the other three sites the same reviews
enumerated. `UNPRINTABLE`'s "only declaration of the tools", the open-object
comment's "only signal that extra keys are accepted", and the docstring
comment's "only description of what a tool does" are each false under
`mode: 'both'`, where the native schemas ship alongside the SDK.

Widen the note's predicate-path sentence past head and last position: a
character added to `XID_Continue` passes `IDENTIFIER`'s trailing quantifier
anywhere after the head, the middle of a name included.

Record the ƛ test's table provenance. U+A7DC and the U+019B mapping to it
both arrive in Unicode 16.0, and the engines floor sits exactly there:
Node 22.19.0 reports Unicode 16.0 (ICU 77.1) and produces the mapping.
2026-08-05 21:53:32 +08:00
Chinesezjc be98a0b978 docs(tools): record the case-mapping read point and narrow the class-name quantifier
`camelCase`'s `toUpperCase()` is a fourth reader of the engine's Unicode
tables, on a table distinct from XID membership and with a wider window: a
tool named U+019B passes `isBareIdentifier` and compiles as `async def` on
CPython 3.9.6, but Node maps the head to U+A7DC and the declared
`class ꟜArgs` fails there with `invalid non-printable character`. Record it
alongside the three XID read points in the renderer docs and in the note's
CPython-floor obligation, and pin the derivation with a test.

Correct three over-quantified sentences: a `camelCase`-derived class name is
evaluated for every tool but only reaches emitted text when some object shape
in the schema declares a `TypedDict`. Attribute the `str.isidentifier()`
equivalence to `IDENTIFIER` rather than to the predicate, which is
deliberately stricter, and restore the antecedent the mode qualification
dropped.
2026-08-05 21:33:30 +08:00
Chinesezjc 2914a87eda fix(tools): widen the Unicode-skew obligation past isBareIdentifier
The predicate is not the only reader of the engine's XID tables. camelCase
reads them through its split set and its head test, and the class name it
derives is emitted for EVERY tool -- including one the predicate rejected,
whose TypedDict is still declared and named. A tool named `zz-` + U+1E4D0
never reaches the skew in the predicate, since the `-` rejects it outright,
yet still emits `class Zz<U+1E4D0>xArgs`, which CPython 3.9.6 refuses the
same way. A backend PR executing "pin the predicate against tables for the
floor" literally would leave that path open, so the note and the docstring
now name all three read points.

Two corrections in the same paragraph. The failing direction is a character
added to XID_Start OR XID_Continue -- one added only to the latter passes
the trailing `\p{XID_Continue}*` in a tail position and fails identically.
And the safe direction routes a name to the subscript/`dict[str, Any]`
path: a rejected FIELD name degrades its whole enclosing object rather than
just itself, which the predicate's opening paragraph already said.

Also qualify the module header's "ONLY source" claim, which holds under
`mode: 'code'` but not `both`, where wireSchemas ships every native schema
alongside the SDK section; record the measured str.isidentifier()
equivalence (21 samples, zero divergence, Node 22.23.1 vs CPython 3.9.6)
where the versions it is relative to already live; and attribute the
`FInd` spelling in the ligature test to full case mapping rather than to
the NFKC step, which is the identity there.

Two tests. The fold-collision half of the childClassName fix: sibling joins
that are byte-distinct before NFKC and equal after, so `usedClassNames`
dedupes by raw bytes and the counter only sees the collision because the
join is normalized. And the argument-side oneOf-of-objects branch naming,
which reaches the same childClassName path the output side already pins.
2026-08-05 21:08:24 +08:00
Chinesezjc 8c001d9928 fix(tools): normalize the two class-name joins camelCase's own call misses
camelCase normalized `joined` and then prefixed, so the seam the `Tool`
prefix creates was never covered: `Tool` ends in `l`, a combining-mark
head composes with it, and a name headed by U+0301 was emitted as
`Tool` + U+0301 while CPython compiles `Too` + U+013A. childClassName
has the same shape -- both sides separately NFKC-stable, their join not:
a base ending in a Hangul L jamo or LV syllable composes with a V or T
jamo head. Beyond the declared-name/compiled-symbol mismatch, two
byte-distinct names can fold onto one, and usedClassNames dedupes by raw
bytes, so the collision counter never sees it. Normalize after the
prefix decision and at the join, before the cap. The remaining joins
need nothing: `Args`/`Output` and the digit suffix cannot compose
backwards.

Also record the Unicode-table skew. The predicate reads the engine's
tables (Node 22.23.1: 17.0) and the interpreter reads its own (CPython
3.9.6: 13.0.0), so an interpreter older than the engine takes a bare
name its tokenizer refuses -- U+1C89, U+10570, U+1E290 and U+1E4D0 are
accepted here and rejected there. The other direction only degrades a
legal name to subscript. Closing it needs the CPython floor, which the
backend PR owns; state the asymmetry in the docstring and make the
decision an explicit obligation in the note.
2026-08-05 20:39:11 +08:00
Chinesezjc 5d65686c33 feat(tools): accept Unicode Python identifiers in the Python SDK renderer
The identifier test was ASCII-only, so an object with a `路径` field
degraded to dict[str, Any] -- dropping every sibling field's name,
requiredness and type, with no native schema behind it in Code Mode to
carry them. Python identifiers are `xid_start xid_continue*`, so match
that instead, and widen camelCase's split and head check to the same
sets (naming `_` explicitly in the split, since it is XID_Continue).

NFKC stability is a second and separate condition. CPython normalizes
identifiers at compile time while a JSON key is compared as written, so
a U+FB01 ligature key would be declared and reachable under its ASCII
expansion, a key the tool never accepts, and two keys that normalize
together would collapse
into one declaration. Those names take the subscript path. Generated
class names are normalized instead of rejected -- they are never matched
against a key. Astral characters can now reach the class-name cap, whose
slice counts UTF-16 code units, so drop a split surrogate half.

Also fix two comment claims. The note said one projection reads the
runtime twice per tool; the language-aware getters are installed on
run_code's own definition, so it is twice, both for that schema. And the
182-bracket site's reachability is an array reached from the root
through oneOf arms alone -- a union spine of any depth, not just one
root union; an object ancestor restarts the chain at the 181 site.
2026-08-05 20:03:39 +08:00
Chinesezjc ba634896e0 docs(tools): name the boundary that rejects a padded integer, and what the flavor-guard test actually reads
pyScalar's docstring attributed the rejection of a String-spelled
beyond-safe-range integer to "the Python runtime". No published backend
makes that call on this base. The fact that does not depend on one: the
padded digits name an integer no double holds, and passing it back would
have to cross the argument boundary as a JSON number. Say that, and say
why String rounds at all -- Number::toString is shortest round-trip, so
2 ** 60 emits the 16 digits that re-read to the same double and pads.
Mirror both in the test comment.

The note's Decision sentence said a test covers the flavor guard through
ctx.tools.schemas(). The test reads the definition's getter directly,
under a language absent from both tables; schemas() reaches the same
getter but has no assertion. Name what is read, and record that a
renderer-without-flavor language is drift this guards against rather
than an existing input -- the two key sets are identical today.
2026-08-05 19:44:05 +08:00
Chinesezjc 015bef2f5f docs(tools): widen the 182 reachability shape and finish the note's two language-binding facts
"Reachable only through a raw register() whose parameters is
array-rooted" was too narrow. A root oneOf reaches the same 182: the
union arm propagates listDepth unchanged because `A | B` opens no
bracket, so an array branch starts its chain at 0 exactly as an array
root does. Say "root opens an array chain -- rooted at the array, or at
an array branch of a root oneOf", in the JSDoc and the test comment,
and assert the union shape alongside the array-rooted one.

The note's Decision paragraph said the flavor guard is reached under
"a language that has a renderer but no flavor entry, and a test covers
it". The test uses ruby, absent from both tables, and the mechanism is
that schemas() reaches run_code's getters without passing
requireCodeRuntime -- so any language absent from the flavor table hits
it. State that instead.

The Consequences paragraph recorded the language-binding obligation as
two reads, assembly and execution. Within one projection there are more:
run_code's description and parameters getters each call
resolveFlavor(peekRuntime()) and schemaOf destructures both, so a reload
between them yields one schema whose halves name different languages.
2026-08-05 19:37:11 +08:00
Chinesezjc 9bba851a62 fix(tools): correct the trim-order claim and check the Literal escape dependency
trim and escape commute for every input, so the new whitespace test does
not pin their order: UNPRINTABLE and LONE_SURROGATE are disjoint from the
set trim() strips, and both escapes emit plain non-whitespace ASCII,
leaving the leading and trailing whitespace runs byte-identical. State that instead of the false causal clause.

pyScalar's Literal path escapes nothing itself -- JSON.stringify is what
keeps it parseable, covering NUL and, under ES2019 well-formed
stringification, unpaired surrogates. Record the dependency and turn it
into a checked invariant. Pin the docstring emission site for a lone
surrogate too, mirroring the NUL case.

Two docstring corrections: describe's caller enumeration omitted the
synthetic { description } wrapper docLines builds, and "special in
statement position" does not describe `_`, which is special in a match
pattern. Both keep the conclusion they support.

Note which of the two table guards fires depends on the entry point.
2026-08-05 18:43:03 +08:00
Chinesezjc 1b4cb031f0 fix(tools): name the two bound SDK names and escape NEL
The static-stub sentence over-generalized: `tools` and `ToolCallError`
ARE bound at run time, and a model reading "everything below is a stub"
could stop catching `ToolCallError`. State the boundary and pin both
halves in the fixed-instruction assertions.

UNPRINTABLE missed U+0085: it is Cc but not ECMAScript whitespace, so
it survived the collapse and reached the docstring raw and invisible.
Add it and scope the docstring to Cc, since the `\xNN` escape cannot
address the Cf formatting characters that pass through by design.

Record the backend PR's two runtime contracts -- inject only `tools`
and `ToolCallError`, and bind the assembly-time language to the
request -- in the Agent Note and at requireCodeRuntime.
2026-08-05 17:45:38 +08:00
Chinesezjc bc94431c34 docs(tools): state the Python SDK declarations are static stubs
A TypedDict reads as a constructible class, so a model that writes
FooArgs(field=1) fails with NameError before dispatch: the run request
injects only the tools namespace and ToolCallError. Say so in
SDK_INSTRUCTIONS and require plain dict/list JSON arguments. The TS
flavor needs no counterpart -- interface is visibly a type and its
"runs type-stripped" clause already covers erasure.
2026-08-05 17:28:58 +08:00
Chinesezjc cc6e4d59fc docs(tools): scope the Python SDK validity standard to the grammar
The list-nesting cap guards against a tokenizer SyntaxError, which makes the
text not Python. A long `A | B | …` union is valid at any length and only
defeats CPython's compile-time C recursion (measured: 1,000 branches compile,
5,000 raise RecursionError); nothing compiles this block, and capping would
retire the deep-chain tests pinning the walk's linear time. Records that
boundary at the `oneOf` arm and in the Agent Note (both languages).

Also documents that the context-free degrade marker reads the call's
className rather than the frame's — frames propagate a derived name, so a
per-frame read would declare classes the caller cannot receive — and pins
that path with oneOf-of-objects and array-of-oneOf assertions.
2026-08-05 15:59:15 +08:00
Chinesezjc 95da760696 fix(tools): cap Python SDK list nesting at CPython's bracket limit
A schema nesting arrays past ~200 levels rendered a `list[list[...]]` chain
CPython's tokenizer rejects outright (`too many nested parentheses`), so the
SDK block was not valid Python at all — the failure docstring escaping in the
same file already guards against. The chain now degrades to `Any` at 180
levels; nesting restarts per TypedDict field, since a field annotation is its
own logical line. Unions and nested objects are unaffected: neither
accumulates open brackets.

Also aligns the unreachable SDK_RENDERERS guard message with the two reachable
ones, and corrects a test comment that still said class docstring.
2026-08-05 14:59:52 +08:00
Chinesezjc 7a178951d6 fix(tools): attach Python SDK docstrings to their own methods
A description was emitted above the `async def`, where Python treats the
first string as the `Tools` class docstring and every later one as a dead
expression — leaving each method undocumented in the model's only source of
tool semantics. Emit it as the first statement of the method body instead.

Also names the known languages in the run_code flavor guard (the reachable
rejection, symmetric with the SDK_RENDERERS guard) and corrects three doc
claims: the code-runtime group README no longer calls the generated SDK
TypeScript, the base Code Mode note states its serial dispatch in past
tense, and the tools README points at the rationale the language-dispatch
note actually carries.
2026-08-05 14:02:47 +08:00
Chinesezjc 0220e06633 docs(tools): scope the Python snapshot obligation and language-neutral concurrency wording 2026-08-05 11:53:17 +08:00
Chinesezjc 13f6af4949 docs(tools): reword the language-dispatch note's two-entries sentence
The Consequences sentence called one of the two table entries "a
SDK_RENDERERS renderer" — circular, since the entry is the renderer mapping.
Reword to "an SDK_RENDERERS entry and a RUN_CODE_FLAVORS entry, plus the
renderer function the former points at" in both languages.
2026-08-02 16:59:50 +08:00
Chinesezjc cabeaed1eb refactor(tools): type the py-types render frame and tighten the note
Follow-ups from the bot's review of the trusted-after-validation revert:
- renderType's Frame now carries JsonSchemaNode (the root schema is asserted
  before any frame is built), dropping the `as Record<string, unknown>` casts,
  the `node.oneOf as unknown[]` cast, and the runtime `required` filter — the
  same typed-frame shape as the sibling ts-types renderer, so the "symmetric
  with ts-types" claim holds structurally, not just behaviorally.
- The language-dispatch note broadens the trusted-input argument to cover all
  real sources (first-party defineTool/raw registration and wire-derived plain
  JSON), and the zh side uses full-width punctuation per translation-rules.md.
py-types.ts stays at 100% per-file coverage.
2026-08-02 16:42:32 +08:00
Chinesezjc f61b138e08 refactor(tools): restore py-types to the ts-types trusted-after-validation stance
Rounds 6-9 of the bot review kept finding adjacent hostile-getter variants
(post-validation cycles, TOCTOU on const/enum/oneOf, self-referential
functions) because the renderer had grown per-shape runtime defenses the
sibling ts-types renderer does not have. Those inputs are unreachable: the
schema is a first-party defineTool object literal that already passed
assertSupportedJsonSchema, and per AGENTS.md "Trust TypeScript at typed
same-process seams" a typed same-process seam does not add hostile-input
handling for values the static interface forbids.

renderType now validates the whole tree once and trusts it, wrapping the walk
in one try/catch that degrades to Any — byte-for-byte the stance of the
ts-types sibling. This removes the cycle-tracking (activeSchemas/hasIdentity),
the const/enum/oneOf read snapshots, the isPyScalar re-check, the typing
rollback, and the pyScalar null->None re-read handling; the corresponding
hostile-getter tests are removed. Behavior fixes that hold for legitimate
input are kept: RESERVED soft-keyword exclusion, closed-empty-object TypedDict,
class-name cap + per-base collision counter, BigInt digits for beyond-safe
integers. py-types.ts stays at 100% per-file coverage.

The language-dispatch Agent Note documents the stance and its symmetry with
ts-types so the boundary is not re-litigated.
2026-08-02 16:25:01 +08:00
Chinesezjc d7b4b014eb fix(tools): make py-types render total and bound deep class names
Address ds-review-bot v5/v6 review round 4:
- renderType now holds the no-throw contract across the whole walk, not
  just root validation: a stateful getter that passes validation and then
  throws in the render phase degrades the node to Any, rolling back any
  classes the call had begun emitting, instead of escaping.
- allocateClassName caps the accumulated base name. Child class names
  derive from their parent's, so an unbounded single-field object chain
  grew the sum of names to Theta(depth^2) (a 5000-deep schema produced a
  ~25MB SDK); the cap keeps total emitted text linear, the collision
  counter still makes truncated bases unique.
- The language-dispatch note's Consequences first sentence and the zh
  guard paragraph are corrected: two table entries (not one), and
  full-width Chinese punctuation per translation-rules.md.
2026-08-02 14:32:35 +08:00
Chinesezjc 59affddfc5 docs(tools): align Code Mode docs with multi-language dispatch; py-types notes
Address ds-review-bot v5/v6 review round 3:
- Config.mode JSDoc and the regenerated config-catalog no longer claim Code
  Mode requires a TypeScript runtime; both now say a language with a
  registered SDK renderer.
- The active 2026-06-15-code-mode base note (both languages) follows shipped
  reality: the SDK renders the loaded runtime's language, dsh-tools accepts
  any language with a renderer and run_code flavor, and it cross-links the
  language-dispatch note.
- The language-dispatch note distinguishes the two Object.hasOwn guards'
  reachability and documents the peekRuntime no-runtime degrade vs the
  rejected silent fallback.
- SDK_RENDERERS comment: adding a language is two table entries, not one.
- py-types: document the deliberate PEP 586 deviation for float Literals;
  add oneOf-object-branch tests (named union classes and context-free
  degrade), keeping py-types.ts at 100% per-file coverage.
2026-08-02 13:55:28 +08:00
Chinesezjc 15e43ee88b fix(tools): satisfy doc gates for the Python SDK renderer
- Delink dsh-code-runtime-python README references (that package ships in
  a later PR of the split; keep the package name unlinked meanwhile).
- Add the mandatory `## Alternatives considered` and `## Consequences`
  sections to the language-dispatch Agent Note.
- Regenerate config/cordis catalogs and the event graph for the shifted
  index.ts source lines; re-record the README and note i18n pairings.
2026-07-31 18:22:25 +08:00
Chinesezjc 4fdfa89d51 feat(tools): render a Python SDK and dispatch Code Mode by runtime language
Code Mode generated only a TypeScript SDK and rejected any runtime whose
language was not "typescript". Add py-types.ts (jsonSchemaToPy /
renderToolsSdkPy) and select the SDK-section renderer and the run_code
schema flavor by ctx.codeRuntime.language through two parallel tables
(SDK_RENDERERS, RUN_CODE_FLAVORS), read with Object.hasOwn and failing
loud on a language with no renderer. The tool layer depends only on the
code-runtime seam's language field, so it lands independently of the
Python protocol and backend.
2026-07-31 18:16:15 +08:00