docs(client-generator): ADRs and helper-surface analysis for the generator rewrite - #3047
Draft
RomanHotsiy wants to merge 2 commits into
Draft
docs(client-generator): ADRs and helper-surface analysis for the generator rewrite#3047RomanHotsiy wants to merge 2 commits into
RomanHotsiy wants to merge 2 commits into
Conversation
…alyze the helper surface Three ADRs for the self-contained generator rewrite, plus the measured inventory they rest on. ADR-0020 makes every generator a self-contained folder ejected as source, replacing the esbuild bundle that inlines already-public toolkit code. ADR-0021 records the text-printer architecture the code already uses and supersedes ADR-0001, which still documents the removed ts.factory codegen. ADR-0022 drops runtime: package for a sibling runtime module, and amends ADR-0017 point 3. helper-surface.md catalogues twelve duplications with file:line evidence. Three are defects rather than untidiness: two TypeScript string escapers with different escaping policies, no escaper at all in python and go, and two pagination resolvers that can disagree about whether an operation paginates.
|
RomanHotsiy
marked this pull request as draft
August 21, 2026 06:43
Contributor
Coverage Report
File CoverageNo changed files found. |
…actored too python, go, and php are already self-contained, so ADR-0020 could be read as leaving them alone — the split was mentioned only as a migration cost. Make it a decision: self-containment was never the goal on its own, and leaving a 953-line python and a 1169-line go whole would keep the asymmetry the ADR removes. Both docs now show the re-grouping is not a rewrite: the existing functions in all three generators sort into the same stages as they are.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What/Why/How?
Design docs only — no code changes. Records the decisions behind the planned
generator rewrite before any of it is implemented, plus the measured analysis
those decisions rest on.
Three ADRs
python/go/phpeject as their own type-stripped source, while the seven TypeScript-family generators esbuild-bundle ~24 modules — the ejectedtypescript.mjsis 178 kB opening with__defPropshims and inlining copies ofauthoring/code that is already public API. Every generator becomes one folder with the same stage skeleton, ejected as.ts— including the single-file generators, which are re-grouped into the same stages rather than grandfathered. Self-containment was never the goal on its own; leaving a 953-linepython/index.tsand a 1169-linego/index.tswhole would keep the very asymmetry this removes. Their existing functions sort into the stages as they are, so it is a re-grouping and not a rewrite. The.replaceAll("'../../authoring/index.js'", …)import rewrite is replaced by real package specifiers plus a guard test.ts.factoryAST codegen;emitters/ts.tsandemitters/package-client.tsno longer exist and every generator emits text. The boundary is syntax vs shape: the printer owns identifier safety, escaping, literals, comments and layout; the generator writes classes and signatures as template literals so the emitted code stays readable in the file the user owns.entry-weight.test.tsexists, it makes the TypeScript runtime dual-purpose, and it silently ignores an ejected runtime the user edited.runtime: 'module'serves its actual purpose — deduplication — while staying zero-dependency.The analysis (
docs/helper-surface.md) is a point-in-time inventory: 87 files, 15,913 lines, 183 exported values, measured by reachability, direct symbol use, and toolkit use.Two findings drove the decisions:
authoring/is not a neutral toolkit in practice — it is the non-TypeScript toolkit. Ten of its sixteen helpers have exactly three consumers, always go/php/python. No TypeScript-family generator usesPrinter,docText,identifierFor, or any schema-shape helper; TypeScript keeps a complete shadow implementation inemitters/.safeIdent,pascalCase,codeLiteral,codeString). The "large shared TypeScript emitter layer" is mostly thetypescriptgenerator's own body living in a shared directory.Twelve duplications are catalogued with
file:lineevidence. Three are defects, not untidiness:codeStringescapes U+2028/U+2029;sanitizeCodeStringalso escapes</>to stop a</script>breakout. Which protection applies depends on which one the caller imported.JSON.stringifycalls.Reference
Follow-up to #3016. Implementation will land in separate PRs against that branch.
Testing
Documentation only; no code changed, so no tests apply. Cross-document links and every cited
file:linewere verified against the source.Note: the pre-commit hook was bypassed.
npm run lintcurrently fails on ~200 pre-existing files across all packages because the localnode_moduleshasoxlint@1.79.0against a declared^1.48.0, so newer rules fire. Zero errors are in the files this PR touches.Screenshots (optional)
Check yourself
Security
No code changes, so no direct security impact. The analysis does document two
existing security-relevant issues for the rewrite to fix: the divergent
TypeScript string-escaping policies (
</script>breakout protection appliesonly on one path) and the absence of any defined escaping policy in the Python
and Go generators.
🤖 Generated with Claude Code
Note
Low Risk
Documentation only; no runtime or API code changes. The ADRs do commit to later breaking removals of package-mode runtime.
Overview
Adds design docs for the planned client-generator rewrite: three accepted ADRs plus a point-in-time helper inventory. No implementation.
ADR-0020 makes every generator a self-contained folder ejected as TypeScript source (no esbuild bundle or import rewrite). ADR-0021 supersedes ADR-0001: codegen is text via a structural
Printerplus per-language syntax printers. ADR-0022 amends ADR-0017 by droppingruntime: 'package'in favor of'inline' | 'module'.helper-surface.mdmeasures sharing (TS-family generators share four functions / 27 lines) and catalogs twelve duplications, including divergent string escapers and two pagination resolvers. The ADR index marks 0001 superseded and 0017 amended.Reviewed by Cursor Bugbot for commit 75f9e00. Bugbot is set up for automated code reviews on this repo. Configure here.