feat(ts-adapter): surface type-reference-reachable types as public API#44
Merged
Conversation
The TS API extractor computed the public surface as only the symbols *named-re-exported* from a package's entry points. A type reachable solely because a public item names it in a type position — e.g. `BashResult` and `RpcSlashCommand`, referenced by the public `RpcResponse`/`BashToolDetails` but never named-re-exported from an entry point — was dropped: it appeared in rendered type strings as a mention only, with zero defined items. Downstream, the api-fluessig converter's cross-package `--context` pass could not resolve such a reference (it stayed `unresolved type reference` and fell back to Json) even with the owning package in context. Close the public surface over type references. Lowering an item now enqueues the in-package, module-exported *type* symbols it names in its type positions (interface members, alias targets, class heritage/members, function params + return), transitively, via a worklist. The walk skips executable bodies so it never promotes a value that merely shares a name with a type, and only promotes types their own module marks `export`, so truly-internal helper types stay excluded and the internal-only fidelity count keeps working. For pi's coding-agent this adds 146 items (0 removed, 0 existing items mutated), including `BashResult` and `RpcSlashCommand` with full field shapes; orchestrator's report is byte-identical (it has no such refs). End to end, full-context conversion drops unresolved type references 10 -> 8 and both types resolve to real models. Also adds notes/api-structured-type-refs.md, a design note proposing an additive v2 of the ApiReport schema (structured `typeRefs` alongside today's rendered strings) so consumers resolve references without re-parsing strings. Depends on #36 (declaration-less-symbol guard) to extract coding-agent without crashing; both target main.
zmaril
force-pushed
the
feat/analyze-reexport-type-surface
branch
from
July 21, 2026 16:18
48a2d7b to
3cc484d
Compare
zmaril
marked this pull request as ready for review
July 21, 2026 21:31
zmaril
enabled auto-merge (squash)
July 21, 2026 21:31
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.
gap-2: surface
export { type … }re-exported types as public APITwo additive pieces for the pi-API parity effort: a concrete TS-extractor fidelity fix, and a design note for a future schema evolution.
Before / After
Before. The TypeScript
hinzu apiextractor computed the public surface as only the symbols named-re-exported from a package's entry points. A type reachable solely because a public item names it in a type position was invisible: it showed up in rendered type strings as a mention, with zero defined items. In pi'scoding-agent,export { type BashResult }(src/core/bash-executor.ts:29) andRpcSlashCommand(src/modes/rpc/rpc-types.ts:79) are referenced by the publicRpcResponse/BashToolDetailsbut never named-re-exported from an entry point, so they emitted 0 items. Downstream, thehinzu api-fluessigconverter's cross-package--contextpass could not resolve those references (they stayedunresolved type referenceand fell back toJson) even withcoding-agentin context.After. The extractor closes the public surface over type references: lowering an item enqueues the in-package, module-
exported type symbols it names in its type positions (interface members, alias targets, class heritage/members, function params + return), transitively, via a worklist.BashResultandRpcSlashCommandare now first-class public items with full field shapes, so downstream cross-package resolution finds them.No regression (measured on pi)
BashResult(5 fields) andRpcSlashCommand(4 fields) now present. Internal-only fidelity count drops 506 → 388 — the newly type-reachable types are no longer counted as internal-only; types nothing public references stay excluded.export(private helpers stay out).Measured unresolved-ref delta
Full-context conversion (
hinzu api-fluessigon the orchestrator report with the coding-agent / agent / ai reports as--context):unresolved type reference: 10 → 8context_expandable:{BashResult, RpcSlashCommand}→{}— both now resolve to real models.Design note
Adds
notes/api-structured-type-refs.md— an additive v2 ApiReport proposal that emits structuredtypeRefsalongside today's rendered type strings, so the converter andapi-diff(#34) resolve references by id instead of re-parsing strings (HINZU_API_VERSION1 → 2 as a capability signal, v1 consumers unaffected). It states honestly that it is 0 orchestrator parity gain — the plateau is already reached via string-parsing — its value is robustness, not coverage. Design only, not an implementation.Dependency
Base is main. Depends on #36 (declaration-less-symbol guard) — needed to extract
coding-agent/aiwithout crashing; #36 also targets main and its guard dedups when it lands.Gates
cargo test -p hinzu-core(86 passed) ·cargo fmt --check·cargo clippy·hinzu check crates/hinzu-core --policy hinzu-self.toml(no violations) · straitjacket v0.2.3 whole-tree on a clean clone (ok — no findings) ·analyze.mjs1337 lines (under 1500).