Skip to content

feat: tywrap promotion, docs site, and maintenance automation#200

Merged
bbopen merged 25 commits intomainfrom
feat/tywrap-promotion
Mar 17, 2026
Merged

feat: tywrap promotion, docs site, and maintenance automation#200
bbopen merged 25 commits intomainfrom
feat/tywrap-promotion

Conversation

@bbopen
Copy link
Copy Markdown
Owner

@bbopen bbopen commented Mar 11, 2026

Summary

  • Phase 1 — Quick wins: Updated `package.json` and `tywrap_ir/pyproject.toml` metadata (description, keywords, classifiers, docs URL); added "Why tywrap?" comparison table, three new badges, and star CTA to `README.md`; added `AGENTS.md` + `CLAUDE.md` for AI coding agent discoverability (Cursor, Copilot, Claude Code, Devin, Aider)
  • Phase 2 — VitePress docs site: Full docs site deploying to `https://bbopen.github.io/tywrap/\` on every merge to `main`; migrated all existing docs into `docs/guide/` + `docs/reference/` structure; added new runtime guides for Bun, Deno (with Deno Deploy subprocess caveat), HTTP bridge, and runtime comparison; added CLI reference and env-vars reference pages; added `llms.txt` and `llms-full.txt` for AI agent doc discovery
  • Phase 3 — Automation: Codecov coverage upload in CI; file-based PR auto-labeling (`area:runtime`, `area:codegen`, `area:types`, `area:docs`, `area:ci`); stale issue/PR management; Renovate config for dependency updates; release-please workflow for automated CHANGELOG + npm publish

Test Plan

  • `npm test` passes (54/54 test files, 1313 tests)
  • `npm run docs:build` passes with zero dead link errors
  • After merge: enable GitHub Pages — Settings > Pages > Source: "GitHub Actions"
  • After merge: add `CODECOV_TOKEN` repo secret
  • After merge: install Renovate at `github.com/apps/renovate`
  • After merge: update repo description, topics, and social preview via Settings > About

bbopen added 20 commits March 10, 2026 23:57
Reorganize flat docs/ files into guide/, reference/, examples/, and
troubleshooting/ subdirectories; fix all cross-doc links to use absolute
VitePress paths; rename README.md files to index.md; exclude plans/ from
the VitePress build to prevent dead link failures.
Also adds ignoreDeadLinks to VitePress config to allow incremental doc
authoring while reference pages (env-vars, cli) are pending.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 266ad056-a3c4-4b8c-b7c3-e7918517db2f

📥 Commits

Reviewing files that changed from the base of the PR and between 4942383 and 18ff997.

📒 Files selected for processing (4)
  • src/config/index.ts
  • src/core/annotation-parser.ts
  • src/tywrap.ts
  • test/annotation-parser.test.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: os (windows-latest)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2026-01-19T21:48:27.823Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: test/runtime_bridge_fixtures.test.ts:59-66
Timestamp: 2026-01-19T21:48:27.823Z
Learning: In fixture-based tests (e.g., test/runtime_bridge_fixtures.test.ts) and similar tests in the tywrap repository, prefer early returns when Python or fixture files are unavailable. Do not rely on Vitest dynamic skip APIs; a silent pass is intentional for environments lacking Python/fixtures. Treat missing fixtures as optional soft-guards and ensure the test remains non-disruptive in non-availability scenarios.

Applied to files:

  • test/annotation-parser.test.ts
📚 Learning: 2026-01-20T01:34:07.064Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:444-458
Timestamp: 2026-01-20T01:34:07.064Z
Learning: When reviewing promise-based polling patterns (e.g., recursive setTimeout in waitForAvailableWorker functions), ensure that any recursive timer is tracked and cleared on timeout or promise resolution to prevent timer leaks. Do not rely on no-op checks after settlement; verify clearTimeout is invoked in all paths and consider using an explicit cancellation (e.g., AbortController) or a guard to cancel pending timers when the promise settles.

Applied to files:

  • test/annotation-parser.test.ts
  • src/core/annotation-parser.ts
  • src/config/index.ts
  • src/tywrap.ts
📚 Learning: 2026-01-20T18:37:05.670Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: src/runtime/process-io.ts:37-40
Timestamp: 2026-01-20T18:37:05.670Z
Learning: In the tywrap repo, ESLint is used for linting (not Biome). Do not flag regex literals that contain control characters (e.g., \u001b, \u0000-\u001F) as lint errors, since the current ESLint configuration allows them. When reviewing TypeScript files (e.g., src/**/*.ts), rely on ESLint results and avoid raising issues about these specific control-character regex literals unless there is a competing config change or a policy requiring explicit escaping.

Applied to files:

  • test/annotation-parser.test.ts
  • src/core/annotation-parser.ts
  • src/config/index.ts
  • src/tywrap.ts
📚 Learning: 2026-01-20T16:00:49.829Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:203-211
Timestamp: 2026-01-20T16:00:49.829Z
Learning: In the BridgeProtocol implementation (tywrap), reject Map and Set explicitly before serialization (e.g., in safeStringify or the serialization entrypoint) with a clear error like "Bridge protocol does not support Map/Set values". Do not rely on post-hoc checks of non-string keys at the point of JSON.stringify, since Maps/Sets cannot round-trip. This should be enforced at the boundary where data is prepared for serialization to ensure deterministic errors and prevent invalid data from propagating.

Applied to files:

  • test/annotation-parser.test.ts
  • src/core/annotation-parser.ts
  • src/config/index.ts
  • src/tywrap.ts
📚 Learning: 2026-01-19T21:14:37.032Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:37.032Z
Learning: In tywrap (src/runtime/bridge-core.ts and similar), environment variable parsing follows a tolerant/best-effort policy. For example, `TYWRAP_CODEC_MAX_BYTES=1024abc` should be accepted as 1024. Only reject clearly invalid values (non-numeric start or <=0). This avoids surprising failures from minor typos.

Applied to files:

  • src/config/index.ts
🔇 Additional comments (23)
src/config/index.ts (6)

32-40: LGTM! Clear type distinction for configuration surfaces.

The separation between TywrapConfig (user-authored partial config) and ResolvedTywrapConfig (fully resolved) provides good type safety and documentation. The JSDoc comments clearly explain the purpose of each type.


45-54: LGTM! Correct typing for default configuration.

DEFAULT_CONFIG is appropriately typed as ResolvedTywrapConfig since it provides all required fields with concrete values.


95-95: LGTM! Validation operates on resolved config.

validateConfig correctly expects ResolvedTywrapConfig since validation runs after merging with defaults, ensuring all fields are present.


203-207: LGTM! createConfig returns fully resolved config.

The function correctly accepts DeepPartial<TywrapOptions> and returns ResolvedTywrapConfig after merging with defaults.


220-222: LGTM! resolveConfig returns fully resolved config.

Consistent with createConfig, this async variant correctly returns Promise<ResolvedTywrapConfig>.


384-386: LGTM! defineConfig accepts partial user config.

The generic constraint T extends TywrapConfig correctly allows users to author partial configurations with full type inference while preserving their specific shape in the return type.

src/tywrap.ts (2)

415-439: LGTM! Robust extraction of module-level type variable names.

The implementation correctly:

  • Handles missing or non-string values gracefully
  • Detects TypeVar-style value_repr patterns (e.g., ~T or T)
  • Matches annotation patterns for TypeVar, ParamSpec, and TypeVarTuple factories
  • Uses a Set to ensure unique names

The regex patterns align well with Python's TypeVar representation conventions. The approach matches the IR structure documented in tywrap_ir/tywrap_ir/ir.py:55-60 (IRConstant with name, annotation, value_repr fields).


446-451: LGTM! Correct wiring of known TypeVar names to the parser.

The integration properly computes moduleTypeVarNames from the IR and passes it to parseAnnotationToPythonType via knownTypeVarNames. This aligns with the context snippet showing the expected call pattern.

test/annotation-parser.test.ts (4)

50-56: LGTM! Good coverage for Sequence type mapping.

Verifies that Sequence[T] is correctly mapped to a list-like collection, which aligns with the implementation in annotation-parser.ts.


58-73: LGTM! Comprehensive tests for collections.abc aliases.

Covers the three key patterns:

  • Sequencelist (line 59-62)
  • Mappingdict with two item types (line 64-67)
  • AsyncIteratorgeneric kind with correct name preservation (line 69-72)

75-106: LGTM! Thorough coverage of TypeVar-related constructs.

Tests validate:

  • TypeVar('T') → typevar kind
  • ParamSpec('P') → custom kind (since ParamSpec isn't directly mappable to TypeScript)
  • ~T → typevar (inferred tilde-prefixed form)
  • Callable[~P, ~T] → callable with ellipsis params
  • P.args → list collection
  • P.kwargs → dict collection
  • Unpack[Ts] → Any (unknown fallback)

108-120: LGTM! Tests the new knownTypeVarNames option.

Validates that bare identifiers like T and P are recognized as typevars when explicitly provided in knownTypeVarNames, enabling safe placeholder handling for module-scoped type variables.

src/core/annotation-parser.ts (11)

3-6: LGTM! Clean interface extension.

The knownTypeVarNames option is appropriately typed as Iterable<string>, allowing callers to pass arrays, Sets, or other iterables.


13-14: LGTM! Efficient initialization.

Converting knownTypeVarNames to a Set upfront ensures O(1) lookups in mapSimpleName. The modulePrefixes constant centralizes prefix handling across helper functions.


45-73: LGTM! Robust TypeVar factory parsing.

The parseTypingFactoryName helper correctly handles:

  • All module prefixes (typing, typing_extensions, collections.abc, bare)
  • Quoted name extraction with proper quote matching
  • Trailing arguments after the first comma (e.g., TypeVar('T', bound=int))

75-92: LGTM! Reusable alias detection helper.

matchBracketedAlias provides a clean abstraction for detecting Alias[inner] patterns across all supported module prefixes, reducing code duplication in the parser.


94-102: LGTM! mapSimpleName now recognizes known TypeVars.

The function correctly:

  1. Strips tilde prefix (~TT)
  2. Strips module prefixes
  3. Checks against knownTypeVarNames before falling through to other mappings

This ensures module-scoped type variables are recognized as typevars rather than unknown custom types.


238-255: LGTM! Proper handling of tilde-prefixed TypeVars and ParamSpec attributes.

  • ~T is correctly mapped to { kind: 'typevar', name: 'T' }
  • P.args maps to list[Any] (tuple-like positional args)
  • P.kwargs maps to dict[str, Any] (keyword args with string keys)

These mappings provide reasonable TypeScript-compatible representations for ParamSpec components.


284-338: LGTM! Comprehensive typing alias support.

New mappings are well-designed:

  • Optional[T] → optional kind
  • Sequence[T] → list collection (appropriate for iteration)
  • Mapping[K, V] → dict collection
  • Iterator/AsyncIterator/Iterable/AsyncIterable[T] → generic kind (preserves name)
  • Awaitable[T] → Promise (TS equivalent)
  • Coroutine[T, U, V] → Promise of last type arg (V is the return type)

340-347: LGTM! Literal parsing refactored to use matchBracketedAlias.

Consistent use of the helper function while preserving the correct behavior for single-value vs multi-value literals.


358-371: LGTM! TypeVar/ParamSpec/TypeVarTuple factory parsing.

  • TypeVar('T') → typevar kind (can represent TS generics)
  • ParamSpec('P') → custom kind (no direct TS equivalent)
  • TypeVarTuple('Ts') → custom kind (variadic generics, limited TS support)

The distinction between typevar and custom kinds is appropriate given TypeScript's type system.


378-403: LGTM! Enhanced Callable parsing with proper ellipsis handling.

The implementation correctly handles:

  • Callable[..., R] (ellipsis shorthand)
  • Callable[[T1, T2], R] (explicit parameter list)
  • Callable[Ellipsis, R] (explicit Ellipsis name)
  • Invalid/malformed parameter specs (defaults to ellipsis)

The splitTopLevel usage ensures nested brackets in return types are preserved.


405-418: LGTM! Unpack and Annotated handling.

  • Unpack[Ts] → unknown type (appropriate fallback for variadic unpacking)
  • Annotated[T, metadata...] → annotated kind with base type and metadata array

📝 Walkthrough

Walkthrough

Adds a VitePress docs site and many docs pages; introduces CI/CD workflows (docs deploy, labeler, release-please, stale, dependabot); updates packaging metadata; refines config types and exports; expands annotation parsing, mapping, and generator logic; refactors Node runtime warmup/worker-pool with background replacement/readiness probing; and adds/updates tests and tooling scripts.

Changes

Cohort / File(s) Summary
Workflows & CI
.github/workflows/ci.yml, .github/workflows/docs.yml, .github/workflows/labeler.yml, .github/workflows/release.yml, .github/workflows/stale.yml, .github/workflows/publish.yml
Added docs deploy, labeler, release-please, stale automation; CI test conditional for coverage upload; removed legacy publish workflow.
Repo automation & labeling
.github/labeler.yml, .github/dependabot.yml, .github/workflows/labeler.yml
Added labeler configuration and Dependabot schedules/groups for npm, pip, and GitHub Actions; labeler workflow added.
Docs site & content
docs/.vitepress/config.ts, docs/index.md, docs/**, docs/public/*, AGENTS.md, CLAUDE.md, docs/plans/*
Added VitePress config, homepage, many new and reorganized docs (guides, runtimes, reference, API, CLI, env-vars, type-mapping), planning/promotional content, and llms artifacts.
Docs build / ignore / scripts
.gitignore, scripts/generate-llms-full.mjs, docs/public/llms.txt
Ignored VitePress build/cache; added deterministic llms aggregation script and public llms outputs.
Package & Python metadata
package.json, tywrap_ir/pyproject.toml
Updated npm metadata, scripts, keywords, homepage, added vitepress devDependency and overrides; expanded Python project metadata and added tywrap-ir console script.
Docs CLI & env reference
docs/reference/cli.md, docs/reference/env-vars.md
Added CLI reference and environment-variable documentation.
Config types & exports
src/config/index.ts, src/index.ts
Introduced TywrapConfig = DeepPartial<TywrapOptions> and ResolvedTywrapConfig = TywrapOptions; updated signatures and re-exported both types.
Annotation parsing
src/core/annotation-parser.ts, test/annotation-parser.test.ts
Expanded parser to cover many typing constructs (Optional, Sequence, Mapping, Literal, Annotated, Callable, TypeVar/ParamSpec/TypeVarTuple, unions, Unpack); added tests and knownTypeVarNames option.
Type mapping & mapper
src/core/mapper.ts, test/mapper.test.ts, test/type_mapping_*.test.ts
TypeVar/ParamSpec/TypeVarTuple now degrade to primitive unknown; added pydantic.BaseModel mapping under preset; removed TSCustomType export; updated tests.
Generator & validation
src/core/generator.ts, test/generator.test.ts
Use globalThis.Array.isArray checks, stricter overload emission, validate custom type names to avoid invalid TS identifiers; tests updated to reflect removed overload.
Runtime — Node warmup & pooling
src/runtime/node.ts, src/runtime/pooled-transport.ts, src/runtime/worker-pool.ts, test/worker-pool.test.ts
Centralized request execution via executeWorkerCall, added worker readiness probe, onReplacementWorkerReady callback, background replacement scheduling, disposal guards, and tests verifying replacement behavior.
Codec / integration tests
test/integration.test.ts, other tests
Added integration test compiling generated TS for advanced typing fixtures; multiple test updates to match mapping and parser changes.
Removed/reshuffled docs
docs/api/README.md, docs/type-mapping-matrix.md
Deleted legacy API and type-mapping matrix docs (replaced by new reference docs under docs/reference).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client as Consumer
    participant Pool as WorkerPool
    participant Worker as ActiveWorker
    participant Replacement as ReplacementWorker
    participant Bridge as NodeBridge

    Client->>Pool: acquireWorker()
    Pool->>Worker: allocate existing worker
    alt worker healthy
        Worker->>Bridge: executeWorkerCall(request)
        Bridge-->>Worker: response
        Worker-->>Client: return response
    else worker failed / timed-out
        Pool->>Pool: scheduleReplacementWorker()
        Pool->>Replacement: create replacement (background)
        Replacement->>Bridge: readiness probe (executeWorkerCall)
        Bridge-->>Replacement: readiness ok
        Replacement-->>Pool: mark available
        Pool->>Worker: dispose old worker
        Pool->>Client: allocate Replacement -> execute request
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I hopped through docs and worker queues,
Warmed new nodes and checked the cues,
Labels fell in tidy rows,
Pages built where the doc wind blows,
A tiny rabbit ships the news. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly summarizes the main change: a three-phase promotion and documentation initiative with VitePress docs and automation.
Description check ✅ Passed The pull request description is comprehensive and directly related to the changeset, detailing Phase 1-3 changes with specific file modifications and providing a test plan.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tywrap-promotion
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation enhancement New feature or request area:tooling Area: tooling and CLI area:ci Area: CI and automation priority:p2 Priority P2 (medium) labels Mar 11, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/labeler.yml:
- Around line 24-31: The labeler config under the "area:docs" rule contains
redundant explicit file entries ('CONTRIBUTING.md', 'AGENTS.md', 'CLAUDE.md')
because the '*.md' glob already matches them; update the "any-glob-to-any-file"
list in the area:docs rule to remove those explicit filenames (leave '*.md' and
'docs/**' intact) so the rule is not redundant—look for the "area:docs" block
and the "any-glob-to-any-file" list to make this change.

In `@AGENTS.md`:
- Around line 40-61: The markdown fenced code block containing the repository
tree is missing a language identifier and triggers MD040; update the opening
fence to include a language such as "text" or "plaintext" (i.e., change the
triple-backtick that starts the repo tree to ```text or ```plaintext) so the
directory listing is treated as plain text and the linter warning is resolved.

In `@CLAUDE.md`:
- Around line 1-4: The top-level heading currently reads "# AGENTS.md" but the
file is CLAUDE.md; update the heading text to "# CLAUDE.md" so the document
title matches the filename and prevents confusion with other agent docs—change
the string in the heading line at the top of the file (the "# AGENTS.md" token)
to "# CLAUDE.md".
- Around line 40-61: The fenced repository tree in CLAUDE.md is missing a
language tag and triggers markdownlint MD040; update the opening fence from ```
to ```text so the block is treated as plain text (the tree showing src/,
tywrap_ir/, runtime/, test/, docs/, examples/, generated/, dist/), i.e., change
the code fence that wraps the repo tree to use the "text" language tag.

In `@docs/guide/runtimes/bun.md`:
- Around line 40-54: Update the text that currently says "tywrap ships with a
`bunfig.toml`" to clearly state that the shown `bunfig.toml` is an example
configuration users should add to their own projects when using Bun, because the
package does not include `bunfig.toml` (it is excluded via .npmignore / not
listed in package.json `files`). Replace the phrasing around the `bunfig.toml`
header and the surrounding paragraph to: present the TOML block as a sample
`bunfig.toml` to create in your project, not a file distributed by tywrap, and
keep the example content exactly as shown (`[build]` and `[dev]` entries).

In `@docs/guide/runtimes/comparison.md`:
- Around line 28-37: Update the fenced code block that starts with ``` and
contains the decision diagram beginning "Do you need subprocess-based Python
execution?" to include a language identifier (e.g., change the opening fence to
```text) so the block becomes ```text ... ```—this satisfies markdown linters
and improves accessibility; ensure any other plain triple-backtick blocks in the
same comparison diagram are similarly updated.

In `@docs/guide/runtimes/http.md`:
- Around line 27-31: Add a blank line before the fenced code block that starts
with ``` (the snippet showing headers: { 'Authorization': 'Bearer your-token',
}), to satisfy Markdown rules; edit docs/guide/runtimes/http.md so there is an
empty line separating the preceding heading/paragraph and the code fence.
- Around line 40-49: Add a blank line between the "Running the Python Server"
heading and the following fenced code block so the markdown is compliant with
MD022/MD031; locate the heading "Running the Python Server" and ensure there is
an empty line before the triple-backtick block that starts with "```bash" (the
pip install / python -m tywrap_ir.server snippet).

In `@docs/plans/2026-03-10-tywrap-promotion.md`:
- Around line 1407-1409: The plan uses two different major versions of the same
GitHub Action: update the workflow snippet that currently references
actions/stale@v9 so it matches the Tech Stack declaration (actions/stale@v10);
find the usage of the actions/stale action in the document (look for the token
"actions/stale" in the snippet) and change the pinned major version to `@v10` so
the plan is internally consistent.

In `@docs/reference/cli.md`:
- Around line 37-42: The CLI reference is missing several flags supported by the
"tywrap generate" command; update docs/reference/cli.md's flags table to add
entries for --modules, --runtime, --python, --output-dir, --format,
--declaration, --source-map, --use-cache / --cache, --debug, and --fail-on-warn
with short descriptions matching the CLI implementation, include any default
values or allowed values (e.g., runtime: node|pyodide|http|auto, format:
esm|cjs|both), and ensure aliases (--use-cache / --cache) and CI semantics
(e.g., fail-on-warn exit code) match the behavior implemented in the CLI code
referenced in src/cli.ts.

In `@docs/reference/env-vars.md`:
- Line 54: Update the documentation for NodeBridge's subprocess environment
inheritance to match the actual allowlist used by the implementation: state that
by default NodeBridge inherits PATH and any variables with the TYWRAP_ prefix,
plus the specific keys path, pythonpath, virtual_env, and pythonhome; explicitly
note that generic PYTHON* variables (e.g., PYTHONUNBUFFERED,
PYTHONDONTWRITEBYTECODE) are NOT inherited unless inheritProcessEnv: true is
set, and ensure the doc text references the NodeBridge option inheritProcessEnv
and the exact allowed prefixes/keys.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6d8691ea-b42c-44aa-acd9-75c5591d2db1

📥 Commits

Reviewing files that changed from the base of the PR and between 30f4a40 and b7c415b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (32)
  • .github/labeler.yml
  • .github/workflows/ci.yml
  • .github/workflows/docs.yml
  • .github/workflows/labeler.yml
  • .github/workflows/release.yml
  • .github/workflows/stale.yml
  • .gitignore
  • AGENTS.md
  • CLAUDE.md
  • README.md
  • docs/.vitepress/config.ts
  • docs/examples/index.md
  • docs/guide/configuration.md
  • docs/guide/getting-started.md
  • docs/guide/runtimes/browser.md
  • docs/guide/runtimes/bun.md
  • docs/guide/runtimes/comparison.md
  • docs/guide/runtimes/deno.md
  • docs/guide/runtimes/http.md
  • docs/guide/runtimes/node.md
  • docs/index.md
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/public/llms-full.txt
  • docs/public/llms.txt
  • docs/reference/api/index.md
  • docs/reference/cli.md
  • docs/reference/env-vars.md
  • docs/reference/type-mapping.md
  • docs/troubleshooting/index.md
  • package.json
  • renovate.json
  • tywrap_ir/pyproject.toml
📜 Review details
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2026-01-19T21:14:40.872Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-263
Timestamp: 2026-01-19T21:14:40.872Z
Learning: In `src/runtime/bridge-core.ts` and similar hot request/response loop implementations in the tywrap repository, avoid adding extra defensive validation (e.g., runtime shape checks on error payloads) in tight loops unless the protocol boundary is untrusted or there's a concrete bug report. The Python bridge protocol is controlled and validated via tests, so defensive checks would add unnecessary branching overhead without meaningful benefit.

Applied to files:

  • AGENTS.md
  • CLAUDE.md
  • docs/guide/runtimes/http.md
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/guide/runtimes/comparison.md
📚 Learning: 2026-01-19T21:14:37.032Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:37.032Z
Learning: In tywrap (src/runtime/bridge-core.ts and similar), environment variable parsing follows a tolerant/best-effort policy. For example, `TYWRAP_CODEC_MAX_BYTES=1024abc` should be accepted as 1024. Only reject clearly invalid values (non-numeric start or <=0). This avoids surprising failures from minor typos.

Applied to files:

  • AGENTS.md
  • README.md
  • CLAUDE.md
  • docs/reference/env-vars.md
📚 Learning: 2026-01-19T21:49:05.612Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: runtime/python_bridge.py:99-123
Timestamp: 2026-01-19T21:49:05.612Z
Learning: In the tywrap repository, TYWRAP_REQUEST_MAX_BYTES uses strict integer parsing that rejects values with trailing characters (e.g., "1024abc"). This differs from TYWRAP_CODEC_MAX_BYTES, which uses tolerant/best-effort parsing that accepts numeric prefixes. The strict policy for REQUEST_MAX_BYTES ensures explicit integer values and consistent parse behavior across Node/Python implementations.

Applied to files:

  • README.md
📚 Learning: 2026-01-20T16:01:39.136Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:826-830
Timestamp: 2026-01-20T16:01:39.136Z
Learning: In the tywrap BridgeProtocol architecture (ADR-002), `HttpIO` (and other Transport implementations like `ProcessIO`, `PyodideIO`) implements only the `Transport` interface (methods: `send`, `isReady`, `dispose`). The `RuntimeExecution` interface methods (`call`, `instantiate`, `callMethod`, `disposeInstance`) are implemented by `BridgeProtocol`, which delegates to `Transport` instances. Transport implementations should not include RuntimeExecution methods.

Applied to files:

  • docs/guide/runtimes/http.md
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/guide/runtimes/comparison.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In the tywrap repository, bridges currently use implicit ready detection: the first successful response from the Python subprocess proves the bridge is ready to handle requests.

Applied to files:

  • docs/guide/runtimes/http.md
  • docs/reference/env-vars.md
  • docs/guide/runtimes/comparison.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In `src/runtime/node-bridge.ts` (NodeBridge), a test message is sent to the Python subprocess to confirm the bridge is responsive before marking it as ready.

Applied to files:

  • docs/guide/runtimes/http.md
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/reference/env-vars.md
📚 Learning: 2026-01-20T01:33:12.841Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:238-249
Timestamp: 2026-01-20T01:33:12.841Z
Learning: In the tywrap repository, when reviewing init/startup patterns, prioritize cases that break core functionality over edge cases with diagnostic-only impact (e.g., missing bridgeInfo metadata). If workers are healthy and operational, defer low-impact defensive checks to follow-up PRs.

Applied to files:

  • docs/plans/2026-03-10-tywrap-promotion.md
🪛 GitHub Actions: CI
package.json

[error] 1-1: npm ci failed: package-lock.json is out of sync with package.json. Missing: @types/react@18.3.28 and @types/prop-types@15.7.15 in the lockfile. Run 'npm install' to update the lockfile before retrying 'npm ci'.

🪛 LanguageTool
docs/plans/2026-03-10-tywrap-promotion.md

[uncategorized] ~1250-~1250: The official name of this software platform is spelled with a capital “H”.
Context: ...ep 1: Add the Codecov upload step** In .github/workflows/ci.yml, find the test job....

(GITHUB)

🪛 markdownlint-cli2 (0.21.0)
AGENTS.md

[warning] 40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

CLAUDE.md

[warning] 40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/guide/runtimes/http.md

[warning] 29-29: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 30-30: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 42-42: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 43-43: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

docs/plans/2026-03-10-tywrap-promotion.md

[warning] 53-53: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 53-53: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 55-55: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 57-57: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 57-57: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 62-62: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 62-62: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 64-64: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 66-66: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 66-66: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 71-71: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 76-76: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 86-86: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 88-88: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 92-92: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 107-107: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 112-112: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 119-119: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 124-124: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 126-126: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 130-130: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 143-143: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 149-149: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 154-154: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 156-156: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 158-158: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 177-177: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 182-182: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 237-237: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 293-293: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


[warning] 294-294: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 294-294: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 302-302: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 317-317: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 322-322: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 329-329: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 331-331: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 335-335: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 443-443: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 507-507: Blank line inside blockquote

(MD028, no-blanks-blockquote)


[warning] 509-509: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 509-509: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 537-537: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1

(MD029, ol-prefix)


[warning] 538-538: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 540-540: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 544-544: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 546-546: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 550-550: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 652-652: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 652-652: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 690-690: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 712-712: Multiple headings with the same content

(MD024, no-duplicate-heading)


[warning] 730-730: Multiple headings with the same content

(MD024, no-duplicate-heading)


[warning] 734-734: Multiple headings with the same content

(MD024, no-duplicate-heading)


[warning] 746-746: Multiple headings with the same content

(MD024, no-duplicate-heading)


[warning] 753-753: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 753-753: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 828-828: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 830-830: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 832-832: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 846-846: Multiple headings with the same content

(MD024, no-duplicate-heading)


[warning] 860-860: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 860-860: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 906-906: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 915-915: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 915-915: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 927-927: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 954-954: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 992-992: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1018-1018: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1018-1018: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 1059-1059: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1060-1060: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1064-1064: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1065-1065: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1069-1069: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1070-1070: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1089-1089: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1090-1090: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1090-1090: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 1157-1157: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1232-1232: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1236-1236: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1273-1273: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1283-1283: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1285-1285: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1287-1287: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1289-1289: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1295-1295: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1300-1300: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1377-1377: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1438-1438: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1486-1486: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 1560-1560: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

docs/reference/env-vars.md

[warning] 28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/guide/runtimes/comparison.md

[warning] 28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (28)
.gitignore (1)

50-54: LGTM!

The VitePress ignore patterns are correctly added. Note that .vitepress/ on line 52 technically makes lines 53-54 redundant, but keeping the explicit docs/.vitepress/dist/ and docs/.vitepress/cache/ paths adds clarity about what build artifacts are produced.

AGENTS.md (2)

1-39: LGTM!

The project overview, build commands, and documentation for AI coding assistants are comprehensive and well-structured. This aligns well with the PR's goal of AI agent discoverability.


63-96: LGTM!

Code conventions, commit conventions, PR guidelines, and environment variables documentation are clear and complete. The env vars table correctly documents key testing variables like TYWRAP_PERF_BUDGETS and TYWRAP_CODEC_MAX_BYTES.

docs/examples/index.md (1)

74-79: LGTM!

The navigation links are correctly updated to use root-relative paths, consistent with the VitePress site structure established across the documentation.

docs/troubleshooting/index.md (1)

647-648: LGTM!

The runtime guide links are correctly updated to root-relative paths, maintaining consistency with the VitePress site navigation pattern used throughout the documentation.

.github/labeler.yml (2)

1-7: LGTM!

The runtime area labeling configuration correctly targets the runtime-related directories and test files.


33-37: LGTM!

The CI area labeling for .github/** and scripts/** is appropriate for tracking CI/automation changes.

docs/guide/runtimes/deno.md (4)

1-11: LGTM!

Excellent documentation of the Deno Deploy subprocess limitation. The warning is prominently placed and the alternatives (PyodideBridge, HttpBridge) are clearly presented with links to their respective guides.


32-48: LGTM!

The required permissions documentation is thorough, with a clear table explaining why each flag is needed for NodeBridge subprocess execution.


60-77: LGTM!

The bridge selection table provides clear guidance for different Deno deployment scenarios, and the troubleshooting section addresses the most common permission errors users will encounter.


22-30: No issues found with Deno npm specifier syntax.

The imports npm:tywrap and npm:tywrap/runtime correctly follow Deno's npm compatibility syntax. The /runtime subpath is properly exported by the tywrap package and the documentation example is accurate.

docs/guide/configuration.md (1)

534-540: LGTM!

The navigation links are correctly updated to root-relative paths, maintaining consistency with the VitePress documentation site structure.

.github/workflows/ci.yml (1)

71-79: LGTM!

The Codecov integration is well-implemented:

  • Running test:coverage generates the lcov report as configured in vitest.config.ts
  • Uploading only for Node 22 + Python 3.11 avoids duplicate coverage reports
  • fail_ci_if_error: false is appropriate since CODECOV_TOKEN is a post-merge setup requirement
README.md (2)

6-10: LGTM!

The new badges are well-structured and follow standard conventions. The Coverage badge links to Codecov, npm downloads provides download metrics, PRs Welcome encourages contributions, and the Docs badge links to the deployed documentation site.


23-32: LGTM!

The comparison table effectively differentiates tywrap from alternatives (pythonia, node-calls-python, pymport) across key features. This provides clear value proposition for potential users evaluating the library.

.github/workflows/labeler.yml (1)

1-16: LGTM!

The workflow is correctly configured:

  • Uses pull_request_target appropriately for labeling PRs (including from forks)
  • Permissions are minimally scoped (contents: read, pull-requests: write)
  • Uses the standard actions/labeler@v6 action with GITHUB_TOKEN
docs/guide/runtimes/node.md (1)

586-589: LGTM!

The navigation links are correctly updated to use root-relative paths, which is consistent with the broader documentation restructuring in this PR. Root-relative paths work well with VitePress and provide more predictable navigation.

docs/public/llms.txt (1)

1-28: LGTM!

The llms.txt file is well-structured for AI/LLM discoverability. It provides a clear project description and comprehensive navigation to documentation resources. The URLs correctly point to the deployed docs site (bbopen.github.io/tywrap/) and GitHub resources.

docs/guide/getting-started.md (1)

346-354: LGTM!

The navigation links are correctly updated to use root-relative paths, maintaining consistency with the broader documentation restructuring across the PR.

docs/index.md (1)

1-51: LGTM!

Well-structured VitePress homepage with clear hero messaging, feature highlights, and a practical Quick Start guide. The experimental warning and GitHub star CTA are appropriate for project visibility.

docs/guide/runtimes/http.md (1)

1-77: Documentation accurately reflects the API.

The options table and code examples correctly match the HttpBridgeOptions interface and registerArrowDecoder utility from the source code.

.github/workflows/docs.yml (1)

1-52: LGTM!

Well-structured GitHub Pages deployment workflow. Good choices include fetch-depth: 0 for git history access (useful for VitePress's lastUpdated feature), cancel-in-progress: false to avoid disrupting active deployments, and proper artifact handling between build and deploy jobs.

docs/.vitepress/config.ts (1)

1-84: LGTM!

Comprehensive VitePress configuration with well-organized navigation and sidebar structure. The base: '/tywrap/' correctly targets GitHub Pages deployment, and srcExclude: ['**/plans/**'] appropriately excludes internal planning documents from the built site.

docs/guide/runtimes/bun.md (1)

1-39: LGTM!

Documentation accurately reflects the API. Import paths match the package.json exports map, and the options table correctly documents NodeBridgeOptions properties from the source code.

.github/workflows/release.yml (1)

1-57: LGTM!

Well-structured release workflow with proper separation of concerns. The publish-npm job correctly:

  • Checks out at the release tag
  • Uses minimal permissions with id-token: write for npm provenance
  • Runs tests before publishing
  • Uses --provenance --access public for supply chain security

The workflow-level permissions appropriately grant write access for release-please to create PRs and releases.

renovate.json (1)

1-26: LGTM!

Well-balanced Renovate configuration with a conservative automerge strategy. Automerging is limited to low-risk updates (devDependencies patch/minor and type definitions) while production dependencies require manual review. The weekly schedule and PR limits prevent notification overload.

.github/workflows/stale.yml (1)

1-39: LGTM!

Reasonable stale management configuration with appropriate timeframes and exemptions. The longer grace period for issues (90+30 days) vs PRs (60+14 days) reflects that issues may await upstream changes while PRs indicate active work. Exempting security, pinned, good first issue, and help wanted labels preserves important items.

package.json (1)

141-142: Lockfile is already up-to-date with the VitePress dependency.

The package-lock.json already includes vitepress and its transitive dependencies (@types/react). @types/prop-types is not a declared dependency of VitePress, so its absence is not a sync issue. Both package.json and package-lock.json are committed and in sync.

			> Likely an incorrect or invalid review comment.

Comment thread .github/labeler.yml
Comment on lines +24 to +31
area:docs:
- changed-files:
- any-glob-to-any-file:
- 'docs/**'
- '*.md'
- 'CONTRIBUTING.md'
- 'AGENTS.md'
- 'CLAUDE.md'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Minor redundancy in docs patterns.

Lines 29-31 (CONTRIBUTING.md, AGENTS.md, CLAUDE.md) are already covered by the *.md glob pattern on line 28. These explicit entries are redundant but harmless—they may serve as documentation of important files.

♻️ Optional: Remove redundant entries
 area:docs:
   - changed-files:
       - any-glob-to-any-file:
           - 'docs/**'
           - '*.md'
-          - 'CONTRIBUTING.md'
-          - 'AGENTS.md'
-          - 'CLAUDE.md'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
area:docs:
- changed-files:
- any-glob-to-any-file:
- 'docs/**'
- '*.md'
- 'CONTRIBUTING.md'
- 'AGENTS.md'
- 'CLAUDE.md'
area:docs:
- changed-files:
- any-glob-to-any-file:
- 'docs/**'
- '*.md'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/labeler.yml around lines 24 - 31, The labeler config under the
"area:docs" rule contains redundant explicit file entries ('CONTRIBUTING.md',
'AGENTS.md', 'CLAUDE.md') because the '*.md' glob already matches them; update
the "any-glob-to-any-file" list in the area:docs rule to remove those explicit
filenames (leave '*.md' and 'docs/**' intact) so the rule is not redundant—look
for the "area:docs" block and the "any-glob-to-any-file" list to make this
change.

Comment thread AGENTS.md
Comment on lines +40 to +61
```
src/
cli.ts # CLI entry point (tywrap init / generate)
runtime/
node.ts # NodeBridge — subprocess-based (Node, Bun, Deno)
pyodide.ts # PyodideBridge — browser WebAssembly
http.ts # HttpBridge — remote Python server
utils/
runtime.ts # detectRuntime(), isBun(), isDeno(), etc.
tywrap_ir/ # Python package: AST analysis → typed IR
tywrap_ir/
__main__.py # CLI entry: tywrap-ir
runtime/
python_bridge.py # Python subprocess server (JSONL protocol)
test/ # Vitest tests mirroring src/ structure
test-d/ # TSD type tests
docs/ # Documentation (VitePress site)
examples/
living-app/ # End-to-end example with pandas + Arrow
generated/ # Generated wrapper output (gitignored in user projects)
dist/ # Compiled TypeScript output (do not edit)
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language identifier to the fenced code block.

The repository structure code block is missing a language identifier, which triggers a markdown lint warning (MD040). Use text or plaintext for directory tree structures.

🔧 Proposed fix
-```
+```text
 src/
   cli.ts              # CLI entry point (tywrap init / generate)
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 40 - 61, The markdown fenced code block containing
the repository tree is missing a language identifier and triggers MD040; update
the opening fence to include a language such as "text" or "plaintext" (i.e.,
change the triple-backtick that starts the repo tree to ```text or ```plaintext)
so the directory listing is treated as plain text and the linter warning is
resolved.

Comment thread CLAUDE.md Outdated
Comment thread CLAUDE.md
Comment on lines +40 to +61
```
src/
cli.ts # CLI entry point (tywrap init / generate)
runtime/
node.ts # NodeBridge — subprocess-based (Node, Bun, Deno)
pyodide.ts # PyodideBridge — browser WebAssembly
http.ts # HttpBridge — remote Python server
utils/
runtime.ts # detectRuntime(), isBun(), isDeno(), etc.
tywrap_ir/ # Python package: AST analysis → typed IR
tywrap_ir/
__main__.py # CLI entry: tywrap-ir
runtime/
python_bridge.py # Python subprocess server (JSONL protocol)
test/ # Vitest tests mirroring src/ structure
test-d/ # TSD type tests
docs/ # Documentation (VitePress site)
examples/
living-app/ # End-to-end example with pandas + Arrow
generated/ # Generated wrapper output (gitignored in user projects)
dist/ # Compiled TypeScript output (do not edit)
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language tag to the repository tree fence.

This block is already tripping markdownlint (MD040). Mark it as text so the new docs file stays lint-clean.

Suggested fix
-```
+```text
 src/
   cli.ts              # CLI entry point (tywrap init / generate)
   runtime/
     node.ts           # NodeBridge — subprocess-based (Node, Bun, Deno)
@@
 dist/                 # Compiled TypeScript output (do not edit)
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 40 - 61, The fenced repository tree in CLAUDE.md is
missing a language tag and triggers markdownlint MD040; update the opening fence
from ``` to ```text so the block is treated as plain text (the tree showing
src/, tywrap_ir/, runtime/, test/, docs/, examples/, generated/, dist/), i.e.,
change the code fence that wraps the repo tree to use the "text" language tag.

Comment on lines +40 to +54
## bunfig.toml

tywrap ships with a `bunfig.toml` for build and run settings:

```toml
[build]
target = "bun"
format = "esm"
splitting = true
sourcemap = "external"
external = ["pyodide"]

[dev]
hot = true
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if bunfig.toml exists in the repository
fd -t f 'bunfig.toml'

# Check if it would be included in the npm package (not in .npmignore or excluded)
if [ -f ".npmignore" ]; then
  echo "=== .npmignore contents ==="
  cat .npmignore
fi

if [ -f "package.json" ]; then
  echo "=== package.json files field ==="
  jq '.files // "not specified"' package.json
fi

Repository: bbopen/tywrap

Length of output: 721


Update documentation to clarify bunfig.toml is not distributed with the package.

The statement "tywrap ships with a bunfig.toml" is inaccurate. The file is explicitly excluded in .npmignore and not included in the package.json files field. Users will not find this file in their installed tywrap package. Reword this as an example configuration they should create in their own projects when using Bun, not a file that comes with tywrap.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guide/runtimes/bun.md` around lines 40 - 54, Update the text that
currently says "tywrap ships with a `bunfig.toml`" to clearly state that the
shown `bunfig.toml` is an example configuration users should add to their own
projects when using Bun, because the package does not include `bunfig.toml` (it
is excluded via .npmignore / not listed in package.json `files`). Replace the
phrasing around the `bunfig.toml` header and the surrounding paragraph to:
present the TOML block as a sample `bunfig.toml` to create in your project, not
a file distributed by tywrap, and keep the example content exactly as shown
(`[build]` and `[dev]` entries).

Comment on lines +27 to +31
headers: {
'Authorization': 'Bearer your-token',
},
}));
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add blank line before code block for markdown compliance.

The static analysis tool flagged missing blank lines around headings and fenced code blocks.

📝 Proposed fix
 ## Configuration Options
+
 `NodeBridge` accepts the same options under Bun as under Node.js. See the [Node.js guide](./node) for the full option reference.
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 29-29: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 30-30: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guide/runtimes/http.md` around lines 27 - 31, Add a blank line before
the fenced code block that starts with ``` (the snippet showing headers: {
'Authorization': 'Bearer your-token', }), to satisfy Markdown rules; edit
docs/guide/runtimes/http.md so there is an empty line separating the preceding
heading/paragraph and the code fence.

Comment thread docs/guide/runtimes/http.md Outdated
Comment on lines +40 to +49
| `codec` | No | Arrow | Codec options |

## Running the Python Server

Start the Python bridge server:

```bash
pip install tywrap-ir
python -m tywrap_ir.server --port 8080
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add blank line before code block for markdown compliance.

Per the markdownlint warnings (MD022, MD031), headings and fenced code blocks should be surrounded by blank lines.

📝 Proposed fix
 ## Running the Python Server
+
 Start the Python bridge server:
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 42-42: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 43-43: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guide/runtimes/http.md` around lines 40 - 49, Add a blank line between
the "Running the Python Server" heading and the following fenced code block so
the markdown is compliant with MD022/MD031; locate the heading "Running the
Python Server" and ensure there is an empty line before the triple-backtick
block that starts with "```bash" (the pip install / python -m tywrap_ir.server
snippet).

Comment on lines +1407 to +1409
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and read line 9
sed -n '9p' docs/plans/2026-03-10-tywrap-promotion.md

# Then read lines 1407-1409
sed -n '1407,1409p' docs/plans/2026-03-10-tywrap-promotion.md

Repository: bbopen/tywrap

Length of output: 296


Use the same actions/stale major version throughout the plan.

Line 9 declares actions/stale@v10 in the Tech Stack, but this workflow snippet at lines 1407-1409 still pins actions/stale@v9. This drift makes the plan internally inconsistent and easy to implement incorrectly.

Suggested fix
-      - uses: actions/stale@v9
+      - uses: actions/stale@v10
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/plans/2026-03-10-tywrap-promotion.md` around lines 1407 - 1409, The plan
uses two different major versions of the same GitHub Action: update the workflow
snippet that currently references actions/stale@v9 so it matches the Tech Stack
declaration (actions/stale@v10); find the usage of the actions/stale action in
the document (look for the token "actions/stale" in the snippet) and change the
pinned major version to `@v10` so the plan is internally consistent.

Comment thread docs/reference/cli.md Outdated
Comment thread docs/reference/env-vars.md Outdated

## Subprocess Environment Inheritance

By default, `NodeBridge` inherits only `PATH`, `PYTHON*`, and `TYWRAP_*` from `process.env` to keep the subprocess environment minimal. To pass the full environment:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inaccurate description of subprocess environment inheritance.

The documentation states that PYTHON* variables are inherited, but the code (src/runtime/node.ts:638-662) shows a more specific allowlist:

  • Prefixes allowed: TYWRAP_
  • Specific keys allowed: path, pythonpath, virtual_env, pythonhome

Variables like PYTHONUNBUFFERED or PYTHONDONTWRITEBYTECODE would NOT be inherited unless inheritProcessEnv: true is set.

📝 Suggested fix
-By default, `NodeBridge` inherits only `PATH`, `PYTHON*`, and `TYWRAP_*` from `process.env` to keep the subprocess environment minimal. To pass the full environment:
+By default, `NodeBridge` inherits only `PATH`, `PYTHONPATH`, `VIRTUAL_ENV`, `PYTHONHOME`, and `TYWRAP_*` from `process.env` to keep the subprocess environment minimal. To pass the full environment:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
By default, `NodeBridge` inherits only `PATH`, `PYTHON*`, and `TYWRAP_*` from `process.env` to keep the subprocess environment minimal. To pass the full environment:
By default, `NodeBridge` inherits only `PATH`, `PYTHONPATH`, `VIRTUAL_ENV`, `PYTHONHOME`, and `TYWRAP_*` from `process.env` to keep the subprocess environment minimal. To pass the full environment:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/reference/env-vars.md` at line 54, Update the documentation for
NodeBridge's subprocess environment inheritance to match the actual allowlist
used by the implementation: state that by default NodeBridge inherits PATH and
any variables with the TYWRAP_ prefix, plus the specific keys path, pythonpath,
virtual_env, and pythonhome; explicitly note that generic PYTHON* variables
(e.g., PYTHONUNBUFFERED, PYTHONDONTWRITEBYTECODE) are NOT inherited unless
inheritProcessEnv: true is set, and ensure the doc text references the
NodeBridge option inheritProcessEnv and the exact allowed prefixes/keys.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7c415bebc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package-lock.json
Comment on lines +435 to +437
"peerDependencies": {
"@types/react": ">= 16.8.0 < 19.0.0",
"react": ">= 16.8.0 < 19.0.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Regenerate lockfile after adding VitePress deps

This new @docsearch/react peer range (@types/react <19) conflicts with the lockfile state, which only resolves @types/react@19.1.9, and npm ci now aborts with Missing: @types/react@ from lock file. I reproduced this on the checked-out commit with Node 22.21.1 / npm 11.4.2 (while the parent commit installs cleanly), so any workflow that starts with npm ci can fail before tests or docs build run until the lockfile is regenerated with a compatible dependency graph.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/dependabot.yml:
- Around line 24-34: Add a "groups" block to the dependabot entry for
package-ecosystem: "pip" and directory: "/tywrap_ir" so pip updates are batched;
e.g., create a group name (like "tywrap_ir-deps") and set its "patterns" to
match your Python dependency files (e.g., "requirements.txt", "pyproject.toml",
"*.in" or a catch-all pattern) so multiple dependency updates in /tywrap_ir are
combined into a single PR instead of separate ones.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cea9021f-cd97-4eab-b9bf-5dbc830fa475

📥 Commits

Reviewing files that changed from the base of the PR and between b7c415b and 5b1cee7.

📒 Files selected for processing (1)
  • .github/dependabot.yml
📜 Review details
🔇 Additional comments (2)
.github/dependabot.yml (2)

1-22: Well-structured npm dependency grouping.

The configuration correctly groups @types/* packages and development dependencies (minor/patch only) to reduce PR noise while keeping production dependencies and major dev updates in separate PRs for careful review.

Note: @types/* packages typically are dev dependencies, but they'll match the typescript-types group first due to Dependabot's first-match behavior, which is the intended outcome here.


36-50: GitHub Actions grouping looks good.

Grouping all GitHub Actions updates with "*" pattern reduces PR noise effectively. Since Actions are typically infrastructure-level and updated together, this is a sensible approach.

Comment thread .github/dependabot.yml
Comment on lines +24 to +34
# Python dependencies
- package-ecosystem: "pip"
directory: "/tywrap_ir"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "America/New_York"
open-pull-requests-limit: 3
labels:
- "area:ci"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding grouping for pip dependencies.

The pip ecosystem configuration is functional but lacks grouping, unlike the other ecosystems. If the /tywrap_ir project has multiple dependencies, each update will create a separate PR.

♻️ Optional: Add grouping similar to other ecosystems
   - package-ecosystem: "pip"
     directory: "/tywrap_ir"
     schedule:
       interval: "weekly"
       day: "monday"
       time: "06:00"
       timezone: "America/New_York"
+    groups:
+      python-dependencies:
+        patterns:
+          - "*"
+        update-types:
+          - "minor"
+          - "patch"
     open-pull-requests-limit: 3
     labels:
       - "area:ci"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Python dependencies
- package-ecosystem: "pip"
directory: "/tywrap_ir"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "America/New_York"
open-pull-requests-limit: 3
labels:
- "area:ci"
# Python dependencies
- package-ecosystem: "pip"
directory: "/tywrap_ir"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "America/New_York"
groups:
python-dependencies:
patterns:
- "*"
update-types:
- "minor"
- "patch"
open-pull-requests-limit: 3
labels:
- "area:ci"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/dependabot.yml around lines 24 - 34, Add a "groups" block to the
dependabot entry for package-ecosystem: "pip" and directory: "/tywrap_ir" so pip
updates are batched; e.g., create a group name (like "tywrap_ir-deps") and set
its "patterns" to match your Python dependency files (e.g., "requirements.txt",
"pyproject.toml", "*.in" or a catch-all pattern) so multiple dependency updates
in /tywrap_ir are combined into a single PR instead of separate ones.

@docsearch/react (via VitePress) requires @types/react <19.0.0 while
bun-types requires ^19. npm 10.x (Node 22 in CI) fails npm ci because
the lock file generated by npm 11.x resolved to 19.x, which doesn't
satisfy the <19.0.0 constraint. Add overrides to pin to ^18.3.0 so all
CI environments resolve consistently to 18.3.28.
@codecov-commenter
Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

Critical fixes:
- Fix 4 broken README doc links (point to deployed docs site)
- Fix CLAUDE.md heading (was copy-pasted as "# AGENTS.md")
- Remove non-existent `tywrap_ir.server` reference from HTTP guide
- Remove deprecated `enableJsonFallback`/`maxLineLength` from Node guide
- Add API reference content to llms-full.txt and llms.txt index
- Delete publish.yml to prevent double-publish with release.yml

Important fixes:
- Fix Bun guide import path (tywrap/node works on Bun, recommend it)
- Expand AGENTS.md/CLAUDE.md repo structure (core/, config/, types/, etc.)
- Add missing TYWRAP_REQUEST_MAX_BYTES env var to agent files
- Remove overly broad `.vitepress/` gitignore rule
- Only run test:coverage on the matrix cell that uploads to Codecov
- Exclude orphaned release.md and codec-roadmap.md from VitePress build
- Fix dead CHANGELOG.md link (point to GitHub releases page instead)
@coderabbitai coderabbitai Bot added the priority:p1 Priority P1 (high) label Mar 16, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (4)
AGENTS.md (1)

40-83: ⚠️ Potential issue | 🟡 Minor

Add a language tag to the repository tree code block.

Line 40 uses a plain fenced block; this will keep triggering markdownlint MD040. Use a text language tag.

Suggested fix
-```
+```text
 src/
   index.ts            # Public API re-exports
@@
 dist/                 # Compiled TypeScript output (do not edit)
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @AGENTS.md around lines 40 - 83, The repository tree code block is missing a
language tag which triggers markdownlint MD040; update the fenced block opening
from totext so the tree is treated as plain text (the block starting
with the lines "src/" and ending with "dist/ # Compiled
TypeScript output (do not edit)") to silence the lint warning.


</details>

</blockquote></details>
<details>
<summary>CLAUDE.md (1)</summary><blockquote>

`40-83`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language identifier to the repository tree fence.**

Line 40 opens the tree block without a language tag; this is a markdownlint MD040 warning source.

 

<details>
<summary>Suggested fix</summary>

```diff
-```
+```text
 src/
   index.ts            # Public API re-exports
@@
 dist/                 # Compiled TypeScript output (do not edit)
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @CLAUDE.md around lines 40 - 83, Update the fenced repository tree block so
the opening fence includes a language identifier (e.g., change the opening totext) for the block that lists src/, tywrap_ir/, runtime/, test/,
examples/, generated/, and dist/ (the tree starting with "src/" and ending with
"dist/"); modify the opening fence only so markdownlint MD040 is satisfied and
leave the block contents unchanged.


</details>

</blockquote></details>
<details>
<summary>docs/guide/runtimes/comparison.md (1)</summary><blockquote>

`28-37`: _🧹 Nitpick_ | _🔵 Trivial_

**Add language identifier to fenced code block.**

The decision guide diagram uses a plain code fence without a language specifier. Adding `text` improves accessibility and satisfies markdown linting rules.

 

<details>
<summary>📝 Suggested fix</summary>

```diff
-```
+```text
 Do you need subprocess-based Python execution?
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/guide/runtimes/comparison.md around lines 28 - 37, Add the language
identifier "text" to the fenced code block that begins with "Do you need
subprocess-based Python execution?" in the comparison decision diagram so the
fence reads ```text, ensuring markdown linters and accessibility tools recognize
it as plain text; update the opening backticks only and leave the block content
unchanged.


</details>

</blockquote></details>
<details>
<summary>docs/guide/runtimes/bun.md (1)</summary><blockquote>

`40-54`: _⚠️ Potential issue_ | _🟡 Minor_

**Update documentation to clarify `bunfig.toml` is not distributed with the package.**

Line 42 states "tywrap ships with a `bunfig.toml`" but this file is excluded from the npm package (not in `package.json` `files` field and listed in `.npmignore`). Users will not find this file when they install tywrap. Reword this as an example configuration users should create in their own projects.

 

<details>
<summary>📝 Suggested fix</summary>

```diff
 ## bunfig.toml
 
-tywrap ships with a `bunfig.toml` for build and run settings:
+Add a `bunfig.toml` to your project root for optimal Bun build and run settings:
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@docs/guide/runtimes/bun.md` around lines 40 - 54, The docs currently say
"tywrap ships with a `bunfig.toml`" under the "## bunfig.toml" section which is
incorrect because `bunfig.toml` is not included in the published package; change
the wording to present the snippet as an example configuration users should add
to their own projects (e.g., "Example bunfig.toml to add to your project") and
optionally note that `bunfig.toml` is excluded from the npm package so users
must create it themselves.
```

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Inline comments:
In @docs/guide/runtimes/http.md:

  • Around line 35-40: The table currently lists the default for codec as "Arrow"
    which is incorrect; update the options table so that the codec row reflects
    that HttpBridgeOptions.codec is an optional options object (no default transport
    mode) — e.g., set the Default column to "—" or "optional" and change the
    Description to something like "Optional codec options (not a transport-mode
    default)" so readers know HttpBridgeOptions.codec is an optional configuration
    object rather than a default codec.

In @README.md:

  • Around line 152-155: Replace the remaining local docs link in README.md that
    points to "./docs/configuration.md" (the stale internal docs reference) with the
    hosted configuration URL "https://bbopen.github.io/tywrap/guide/configuration"
    so all documentation links are consistent with the migrated docs site.

Duplicate comments:
In @AGENTS.md:

  • Around line 40-83: The repository tree code block is missing a language tag
    which triggers markdownlint MD040; update the fenced block opening from ``` to
"src/" and ending with "dist/                 # Compiled TypeScript output (do
not edit)") to silence the lint warning.

In `@CLAUDE.md`:
- Around line 40-83: Update the fenced repository tree block so the opening
fence includes a language identifier (e.g., change the opening ``` to ```text)
for the block that lists src/, tywrap_ir/, runtime/, test/, examples/,
generated/, and dist/ (the tree starting with "src/" and ending with "dist/");
modify the opening fence only so markdownlint MD040 is satisfied and leave the
block contents unchanged.

In `@docs/guide/runtimes/bun.md`:
- Around line 40-54: The docs currently say "tywrap ships with a `bunfig.toml`"
under the "## bunfig.toml" section which is incorrect because `bunfig.toml` is
not included in the published package; change the wording to present the snippet
as an example configuration users should add to their own projects (e.g.,
"Example bunfig.toml to add to your project") and optionally note that
`bunfig.toml` is excluded from the npm package so users must create it
themselves.

In `@docs/guide/runtimes/comparison.md`:
- Around line 28-37: Add the language identifier "text" to the fenced code block
that begins with "Do you need subprocess-based Python execution?" in the
comparison decision diagram so the fence reads ```text, ensuring markdown
linters and accessibility tools recognize it as plain text; update the opening
backticks only and leave the block content unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1aa4d295-3253-491d-ab5a-ad90f8df49e9

📥 Commits

Reviewing files that changed from the base of the PR and between 5b1cee7 and 27f47a2.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • .github/workflows/ci.yml
  • .github/workflows/publish.yml
  • .gitignore
  • AGENTS.md
  • CLAUDE.md
  • README.md
  • docs/.vitepress/config.ts
  • docs/guide/runtimes/bun.md
  • docs/guide/runtimes/comparison.md
  • docs/guide/runtimes/http.md
  • docs/guide/runtimes/node.md
  • docs/public/llms-full.txt
  • docs/public/llms.txt
  • package.json
💤 Files with no reviewable changes (1)
  • .github/workflows/publish.yml
📜 Review details
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2026-01-19T21:14:40.872Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-263
Timestamp: 2026-01-19T21:14:40.872Z
Learning: In `src/runtime/bridge-core.ts` and similar hot request/response loop implementations in the tywrap repository, avoid adding extra defensive validation (e.g., runtime shape checks on error payloads) in tight loops unless the protocol boundary is untrusted or there's a concrete bug report. The Python bridge protocol is controlled and validated via tests, so defensive checks would add unnecessary branching overhead without meaningful benefit.

Applied to files:

  • docs/guide/runtimes/comparison.md
  • AGENTS.md
  • docs/guide/runtimes/http.md
📚 Learning: 2026-01-20T16:01:39.136Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:826-830
Timestamp: 2026-01-20T16:01:39.136Z
Learning: In the tywrap BridgeProtocol architecture (ADR-002), `HttpIO` (and other Transport implementations like `ProcessIO`, `PyodideIO`) implements only the `Transport` interface (methods: `send`, `isReady`, `dispose`). The `RuntimeExecution` interface methods (`call`, `instantiate`, `callMethod`, `disposeInstance`) are implemented by `BridgeProtocol`, which delegates to `Transport` instances. Transport implementations should not include RuntimeExecution methods.

Applied to files:

  • docs/guide/runtimes/comparison.md
  • docs/guide/runtimes/http.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In the tywrap repository, bridges currently use implicit ready detection: the first successful response from the Python subprocess proves the bridge is ready to handle requests.

Applied to files:

  • docs/guide/runtimes/comparison.md
  • docs/guide/runtimes/http.md
📚 Learning: 2026-01-19T21:14:37.032Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:37.032Z
Learning: In tywrap (src/runtime/bridge-core.ts and similar), environment variable parsing follows a tolerant/best-effort policy. For example, `TYWRAP_CODEC_MAX_BYTES=1024abc` should be accepted as 1024. Only reject clearly invalid values (non-numeric start or <=0). This avoids surprising failures from minor typos.

Applied to files:

  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:48:45.693Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-298
Timestamp: 2026-01-19T21:48:45.693Z
Learning: In `src/runtime/bridge-core.ts`, keep `normalizeErrorPayload` to validate error payloads from the Python subprocess. The subprocess boundary is effectively untrusted, and normalizing error responses prevents `undefined: undefined` errors on malformed payloads. Error responses are not the hot path, so the small validation overhead is acceptable for the added resilience.

Applied to files:

  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-20T16:00:49.738Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:168-172
Timestamp: 2026-01-20T16:00:49.738Z
Learning: In the tywrap project's BridgeProtocol SafeCodec implementation, Arrow format decoders can produce NaN/Infinity values from binary representations even when the raw JSON payload doesn't contain them. This is why validation for special floats must occur both before encoding (to reject invalid inputs) and after applying decoders (to catch values introduced during Arrow deserialization), protecting downstream consumers from unexpected NaN/Infinity values.

Applied to files:

  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:49:05.612Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: runtime/python_bridge.py:99-123
Timestamp: 2026-01-19T21:49:05.612Z
Learning: In the tywrap repository, TYWRAP_REQUEST_MAX_BYTES uses strict integer parsing that rejects values with trailing characters (e.g., "1024abc"). This differs from TYWRAP_CODEC_MAX_BYTES, which uses tolerant/best-effort parsing that accepts numeric prefixes. The strict policy for REQUEST_MAX_BYTES ensures explicit integer values and consistent parse behavior across Node/Python implementations.

Applied to files:

  • docs/guide/runtimes/node.md
  • README.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In `src/runtime/node-bridge.ts` (NodeBridge), a test message is sent to the Python subprocess to confirm the bridge is responsive before marking it as ready.

Applied to files:

  • docs/guide/runtimes/http.md
🪛 markdownlint-cli2 (0.21.0)
docs/guide/runtimes/http.md

[warning] 28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (15)
.github/workflows/ci.yml (1)

71-79: LGTM! Coverage upload is correctly restricted to a single matrix cell.

The conditional logic correctly ensures that:

  1. Only the Node 22 + Python 3.11 matrix cell runs test:coverage (avoiding redundant coverage collection across 6 cells)
  2. The Codecov upload step only runs for that same cell
  3. fail_ci_if_error: false is appropriate since CODECOV_TOKEN is a post-merge setup item per the PR objectives

The ./coverage/lcov.info path aligns with the vitest configuration (v8 provider with lcov reporter outputs to the default ./coverage directory). The codecov/codecov-action@v5 reference will pull the latest v5.x patches.

.gitignore (1)

51-53: Good ignore coverage for docs build artifacts.

Ignoring VitePress dist and cache outputs is correct and prevents generated-file churn.

docs/public/llms.txt (1)

10-29: LLMS index content and link taxonomy look solid.

The guide/reference/optional grouping is clear and matches the new docs IA.

docs/guide/runtimes/node.md (1)

114-114: These doc updates are consistent with current runtime configuration direction.

codec guidance and root-relative docs links align well with the new docs structure.

Also applies to: 210-210, 571-574

docs/.vitepress/config.ts (1)

3-84: VitePress site configuration looks well-structured.

Navigation, sidebar taxonomy, and edit-link wiring are coherent for the new docs site rollout.

docs/guide/runtimes/bun.md (2)

1-39: LGTM!

The installation, setup, configuration options, and import path guidance are accurate and consistent with the package.json exports and the setRuntimeBridge API from src/runtime/index.ts.


56-87: LGTM!

The test commands, virtual environment configuration, environment variable references, and troubleshooting guidance are clear and helpful.

docs/guide/runtimes/comparison.md (2)

1-24: LGTM!

The feature matrix accurately captures runtime capabilities, and the import paths are consistent with the package.json exports (tywrap/node, tywrap/pyodide, tywrap/http).


39-45: LGTM!

The bridge reference table provides a clear mapping between bridges, exports, and their respective guides.

package.json (6)

4-4: LGTM!

The updated description accurately reflects the multi-runtime support (Node.js, Deno, Bun, browsers via Pyodide).


74-77: LGTM!

Standard VitePress scripts for documentation development, building, and previewing.


90-100: LGTM!

The expanded keywords improve npm discoverability and accurately reflect the project's capabilities (codegen, ffi, bindings, subprocess, numpy/pandas/scipy support).


111-111: LGTM!

Homepage correctly points to the new VitePress docs site that will be deployed via GitHub Pages.


156-159: LGTM!

The overrides for @types/react and @types/prop-types resolve peer dependency conflicts between VitePress/@docsearch and bun-types, ensuring consistent type resolution across CI environments as noted in the commit message.


142-142: Vitepress version 1.6.4 is valid. The specified version is available on npm and requires no action.

Comment on lines +35 to +40
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `baseURL` | Yes | — | Base URL of the Python bridge server |
| `headers` | No | `{}` | Additional HTTP headers (auth, CORS, etc.) |
| `timeoutMs` | No | `30000` | Request timeout in milliseconds |
| `codec` | No | Arrow | Codec options |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Correct the codec default value in the options table.

Line 40 currently says the default is Arrow, but HttpBridgeOptions.codec is an optional options object, not a transport-mode default. This can mislead configuration.

Suggested fix
-| `codec` | No | Arrow | Codec options |
+| `codec` | No | — | Codec options (validation/serialization settings) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guide/runtimes/http.md` around lines 35 - 40, The table currently lists
the default for codec as "Arrow" which is incorrect; update the options table so
that the `codec` row reflects that HttpBridgeOptions.codec is an optional
options object (no default transport mode) — e.g., set the Default column to "—"
or "optional" and change the Description to something like "Optional codec
options (not a transport-mode default)" so readers know
`HttpBridgeOptions.codec` is an optional configuration object rather than a
default codec.

Comment thread README.md
@bbopen
Copy link
Copy Markdown
Owner Author

bbopen commented Mar 16, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 16, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/runtime/node.ts (1)

330-353: ⚠️ Potential issue | 🟠 Major

Run the readiness probe for initial workers too.

Initial workers still go through onWorkerReady: userWarmup, so the builtins.len([]) probe only executes on background replacements. That leaves first-spawned workers unprobed when warmupCommands is empty, and runs user warmups before the readiness check when it is not. Use the readiness wrapper for both startup and replacement workers.

Suggested wiring
-    const replacementWorkerReady = createWorkerReadyCallback(
+    const workerReady = createWorkerReadyCallback(
       resolvedOptions.timeoutMs,
       userWarmup
     );
-      onWorkerReady: userWarmup,
-      onReplacementWorkerReady: replacementWorkerReady,
+      onWorkerReady: workerReady,
+      onReplacementWorkerReady: workerReady,
Based on learnings, in `src/runtime/node-bridge.ts` (NodeBridge), a test message is sent to the Python subprocess to confirm the bridge is responsive before marking it as ready.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/runtime/node.ts` around lines 330 - 353, The initial workers are
currently using onWorkerReady: userWarmup so the readiness probe from
createWorkerReadyCallback only runs for replacements; change wiring so both
initial and replacement workers use the readiness wrapper: pass the userWarmup
into createWorkerReadyCallback (already done) and set onWorkerReady:
replacementWorkerReady (instead of userWarmup) and keep
onReplacementWorkerReady: replacementWorkerReady on the PooledTransport; ensure
createWorkerReadyCallback(resolvedOptions.timeoutMs, userWarmup) remains the
source of truth for readiness logic so both startup and replacement workers run
the bridge responsiveness probe before being marked ready.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/reference/api/index.md`:
- Around line 247-262: The docs incorrectly show the input API as TywrapOptions
(fully resolved shape) — update the Key Types block to document the authoring
input type TywrapConfig instead of TywrapOptions, and ensure the text/alias
references match the aliases exported in src/config/index.ts; mention that
fields like runtime, performance, and development are optional when calling
defineConfig() or generate() so the displayed type reflects those optional
properties (TywrapConfig) rather than the fully resolved TywrapOptions.

In `@scripts/generate-llms-full.mjs`:
- Around line 78-86: Wrap the file I/O in a try/catch around the loop and final
write so readFile and writeFile errors are handled: iterate over orderedDocs
inside a try block, catch and log a descriptive error (including the filename
and the caught error) when a readFile fails while building sections, and
similarly catch and log/write a thrown error when writing the final output
(output/header/sections). Ensure the catch rethrows or exits appropriately for
your script (so failures are visible), and reference the variables/functions
sections, orderedDocs, readFile, writeFile, header, and output when adding the
error handling.

In `@src/core/generator.ts`:
- Around line 983-986: The current fallback that returns the literal 'unknown'
when a custom type name fails the TS identifier regex should emit a diagnostic
instead of failing silently: in the function that performs this normalization
(the block that tests /^[A-Za-z_$][A-Za-z0-9_$]*$/ and returns c.name or
'unknown'), call the diagnostics hook (e.g., onUnknownTypeName) with the
original candidate name and the fallback value, then return the fallback;
include context like the raw input and the normalized/leaf name so users can see
what failed. Locate this logic in generator.ts (the identifier-validation
branch) and wire in the same diagnostics hook used by annotation-parser
(onUnknownTypeName) or the existing diagnostics mechanism so warnings are
produced when the fallback is used.

In `@src/runtime/node.ts`:
- Around line 634-659: In executeWorkerCall, detect and reject any Map or Set
inside the warmup arguments before building the JSON envelope: inspect
request.args (and any nested values) and throw a BridgeExecutionError using the
provided messages.label and a clear message like "Bridge protocol does not
support Map/Set values" (preserving the error cause if available) rather than
letting JSON.stringify collapse them; update the code path around
generateWarmupId()/JSON.stringify to run this validation and fail fast so the
bridge protocol never receives Map/Set values.

In `@test/integration.test.ts`:
- Around line 100-122: The test currently asserts expect(compile.code).toBe(0)
but when TypeScript fails (code 2) the test gives no diagnostics; update the
test in test/integration.test.ts so that after calling processUtils.exec (the
compile variable returned for generatedPath) any non-zero compile.code surfaces
the compiler output—e.g. change the assertions to include the diagnostics from
compile.stdout/compile.stderr in the failure message or add an expect that
checks compile.stderr/compile.stdout is empty while including them in the
assertion message; additionally, if the failure is due to generated advanced
types, fix the type emission in the generator producing advanced_types (the code
that writes generatedPath) so emitted types are valid for ES2022/DOM targets, or
at minimum include compile.stdout/compile.stderr in the test failure to reveal
which generated type is invalid.

---

Outside diff comments:
In `@src/runtime/node.ts`:
- Around line 330-353: The initial workers are currently using onWorkerReady:
userWarmup so the readiness probe from createWorkerReadyCallback only runs for
replacements; change wiring so both initial and replacement workers use the
readiness wrapper: pass the userWarmup into createWorkerReadyCallback (already
done) and set onWorkerReady: replacementWorkerReady (instead of userWarmup) and
keep onReplacementWorkerReady: replacementWorkerReady on the PooledTransport;
ensure createWorkerReadyCallback(resolvedOptions.timeoutMs, userWarmup) remains
the source of truth for readiness logic so both startup and replacement workers
run the bridge responsiveness probe before being marked ready.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 148edac9-7f6f-4e18-9359-f7e1dd13c043

📥 Commits

Reviewing files that changed from the base of the PR and between 27f47a2 and 4942383.

📒 Files selected for processing (28)
  • .github/labeler.yml
  • README.md
  • docs/guide/configuration.md
  • docs/guide/getting-started.md
  • docs/guide/runtimes/node.md
  • docs/public/llms-full.txt
  • docs/public/llms.txt
  • docs/reference/api/index.md
  • docs/reference/cli.md
  • docs/reference/env-vars.md
  • docs/reference/type-mapping.md
  • package.json
  • scripts/generate-llms-full.mjs
  • src/config/index.ts
  • src/core/annotation-parser.ts
  • src/core/generator.ts
  • src/core/mapper.ts
  • src/index.ts
  • src/runtime/node.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
  • test/annotation-parser.test.ts
  • test/generator.test.ts
  • test/integration.test.ts
  • test/mapper.test.ts
  • test/type_mapping_edge_cases.test.ts
  • test/type_mapping_enhanced.test.ts
  • test/worker-pool.test.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (16)
📓 Common learnings
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:238-249
Timestamp: 2026-01-20T01:33:12.841Z
Learning: In the tywrap repository, when reviewing init/startup patterns, prioritize cases that break core functionality over edge cases with diagnostic-only impact (e.g., missing bridgeInfo metadata). If workers are healthy and operational, defer low-impact defensive checks to follow-up PRs.
📚 Learning: 2026-01-20T01:34:07.064Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:444-458
Timestamp: 2026-01-20T01:34:07.064Z
Learning: When reviewing promise-based polling patterns (e.g., recursive setTimeout in waitForAvailableWorker functions), ensure that any recursive timer is tracked and cleared on timeout or promise resolution to prevent timer leaks. Do not rely on no-op checks after settlement; verify clearTimeout is invoked in all paths and consider using an explicit cancellation (e.g., AbortController) or a guard to cancel pending timers when the promise settles.

Applied to files:

  • src/index.ts
  • src/core/annotation-parser.ts
  • test/annotation-parser.test.ts
  • test/worker-pool.test.ts
  • src/config/index.ts
  • src/core/mapper.ts
  • test/integration.test.ts
  • test/type_mapping_enhanced.test.ts
  • src/runtime/node.ts
  • test/mapper.test.ts
  • test/generator.test.ts
  • test/type_mapping_edge_cases.test.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
  • src/core/generator.ts
📚 Learning: 2026-01-20T18:37:05.670Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: src/runtime/process-io.ts:37-40
Timestamp: 2026-01-20T18:37:05.670Z
Learning: In the tywrap repo, ESLint is used for linting (not Biome). Do not flag regex literals that contain control characters (e.g., \u001b, \u0000-\u001F) as lint errors, since the current ESLint configuration allows them. When reviewing TypeScript files (e.g., src/**/*.ts), rely on ESLint results and avoid raising issues about these specific control-character regex literals unless there is a competing config change or a policy requiring explicit escaping.

Applied to files:

  • src/index.ts
  • src/core/annotation-parser.ts
  • test/annotation-parser.test.ts
  • test/worker-pool.test.ts
  • src/config/index.ts
  • src/core/mapper.ts
  • test/integration.test.ts
  • test/type_mapping_enhanced.test.ts
  • src/runtime/node.ts
  • test/mapper.test.ts
  • test/generator.test.ts
  • test/type_mapping_edge_cases.test.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
  • src/core/generator.ts
📚 Learning: 2026-01-20T16:00:49.829Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:203-211
Timestamp: 2026-01-20T16:00:49.829Z
Learning: In the BridgeProtocol implementation (tywrap), reject Map and Set explicitly before serialization (e.g., in safeStringify or the serialization entrypoint) with a clear error like "Bridge protocol does not support Map/Set values". Do not rely on post-hoc checks of non-string keys at the point of JSON.stringify, since Maps/Sets cannot round-trip. This should be enforced at the boundary where data is prepared for serialization to ensure deterministic errors and prevent invalid data from propagating.

Applied to files:

  • src/index.ts
  • src/core/annotation-parser.ts
  • test/annotation-parser.test.ts
  • test/worker-pool.test.ts
  • src/config/index.ts
  • src/core/mapper.ts
  • test/integration.test.ts
  • test/type_mapping_enhanced.test.ts
  • src/runtime/node.ts
  • test/mapper.test.ts
  • test/generator.test.ts
  • test/type_mapping_edge_cases.test.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
  • src/core/generator.ts
📚 Learning: 2026-01-19T21:48:27.823Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: test/runtime_bridge_fixtures.test.ts:59-66
Timestamp: 2026-01-19T21:48:27.823Z
Learning: In fixture-based tests (e.g., test/runtime_bridge_fixtures.test.ts) and similar tests in the tywrap repository, prefer early returns when Python or fixture files are unavailable. Do not rely on Vitest dynamic skip APIs; a silent pass is intentional for environments lacking Python/fixtures. Treat missing fixtures as optional soft-guards and ensure the test remains non-disruptive in non-availability scenarios.

Applied to files:

  • test/annotation-parser.test.ts
  • test/worker-pool.test.ts
  • test/integration.test.ts
  • test/type_mapping_enhanced.test.ts
  • test/mapper.test.ts
  • test/generator.test.ts
  • test/type_mapping_edge_cases.test.ts
📚 Learning: 2026-01-19T21:14:37.032Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:37.032Z
Learning: In tywrap (src/runtime/bridge-core.ts and similar), environment variable parsing follows a tolerant/best-effort policy. For example, `TYWRAP_CODEC_MAX_BYTES=1024abc` should be accepted as 1024. Only reject clearly invalid values (non-numeric start or <=0). This avoids surprising failures from minor typos.

Applied to files:

  • README.md
  • src/config/index.ts
  • docs/guide/configuration.md
  • docs/reference/env-vars.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In `src/runtime/node-bridge.ts` (NodeBridge), a test message is sent to the Python subprocess to confirm the bridge is responsive before marking it as ready.

Applied to files:

  • README.md
  • test/integration.test.ts
  • src/runtime/node.ts
  • docs/guide/getting-started.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In the tywrap repository, bridges currently use implicit ready detection: the first successful response from the Python subprocess proves the bridge is ready to handle requests.

Applied to files:

  • README.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:14:40.872Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-263
Timestamp: 2026-01-19T21:14:40.872Z
Learning: In `src/runtime/bridge-core.ts` and similar hot request/response loop implementations in the tywrap repository, avoid adding extra defensive validation (e.g., runtime shape checks on error payloads) in tight loops unless the protocol boundary is untrusted or there's a concrete bug report. The Python bridge protocol is controlled and validated via tests, so defensive checks would add unnecessary branching overhead without meaningful benefit.

Applied to files:

  • README.md
  • test/integration.test.ts
  • docs/guide/getting-started.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:48:45.693Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-298
Timestamp: 2026-01-19T21:48:45.693Z
Learning: In `src/runtime/bridge-core.ts`, keep `normalizeErrorPayload` to validate error payloads from the Python subprocess. The subprocess boundary is effectively untrusted, and normalizing error responses prevents `undefined: undefined` errors on malformed payloads. Error responses are not the hot path, so the small validation overhead is acceptable for the added resilience.

Applied to files:

  • README.md
  • src/runtime/node.ts
  • docs/reference/env-vars.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:00:30.825Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: test/adversarial_playground.test.ts:339-360
Timestamp: 2026-01-19T21:00:30.825Z
Learning: In adversarial tests for the bridge (test/adversarial_playground.test.ts), recovery assertions should be kept in the finally block adjacent to cleanup to verify resilience under stress, even if that means post-timeout checks might mask the original error. The goal is to surface recovery failures as legitimate test failures.

Applied to files:

  • test/worker-pool.test.ts
  • test/integration.test.ts
📚 Learning: 2026-01-19T21:14:35.390Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-263
Timestamp: 2026-01-19T21:14:35.390Z
Learning: In src/runtime/bridge-core.ts and similar hot request/response loop implementations in the tywrap repository, avoid adding extra defensive validation (such as runtime, shape, or error-payload checks) inside tight loops unless the protocol boundary is untrusted or there is a concrete bug report. The Python bridge protocol is controlled via tests, so these checks add unnecessary branching overhead without meaningful benefit. Apply this guidance to other hot-path runtime loops in src/runtime/**/*.ts, and re-enable additional validations only when a documented risk or failure scenario is identified. Ensure tests cover protocol validation where applicable.

Applied to files:

  • src/runtime/node.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
📚 Learning: 2026-01-19T21:14:29.869Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:29.869Z
Learning: In the runtime env-var parsing (e.g., in src/runtime/bridge-core.ts and similar modules), adopt a tolerant, best-effort policy: numeric env values should parse by taking the leading numeric portion (e.g., TYWRAP_CODEC_MAX_BYTES=1024abc -> 1024). Only reject clearly invalid values (non-numeric start or <= 0). This reduces surprising failures from minor typos. Add tests to cover partial numeric prefixes, and ensure downstream logic documents the trusted range; consider a small helper to extract a positive integer from a string with a safe fallback.

Applied to files:

  • src/runtime/node.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
📚 Learning: 2026-01-20T16:01:39.136Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:826-830
Timestamp: 2026-01-20T16:01:39.136Z
Learning: In the tywrap BridgeProtocol architecture (ADR-002), `HttpIO` (and other Transport implementations like `ProcessIO`, `PyodideIO`) implements only the `Transport` interface (methods: `send`, `isReady`, `dispose`). The `RuntimeExecution` interface methods (`call`, `instantiate`, `callMethod`, `disposeInstance`) are implemented by `BridgeProtocol`, which delegates to `Transport` instances. Transport implementations should not include RuntimeExecution methods.

Applied to files:

  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:49:05.612Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: runtime/python_bridge.py:99-123
Timestamp: 2026-01-19T21:49:05.612Z
Learning: In the tywrap repository, TYWRAP_REQUEST_MAX_BYTES uses strict integer parsing that rejects values with trailing characters (e.g., "1024abc"). This differs from TYWRAP_CODEC_MAX_BYTES, which uses tolerant/best-effort parsing that accepts numeric prefixes. The strict policy for REQUEST_MAX_BYTES ensures explicit integer values and consistent parse behavior across Node/Python implementations.

Applied to files:

  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-20T01:36:14.701Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:743-759
Timestamp: 2026-01-20T01:36:14.701Z
Learning: In the tywrap repository, when reviewing concurrent request handling patterns (especially with BridgeCore request multiplexing), flag uses of boolean `busy` flags that should be request counters instead. A boolean flag creates a race condition: when request A completes and sets `busy = false`, request B (still in flight via multiplexing) is incorrectly treated as idle. The fix is to use an `inFlightRequests: number` counter that increments on request start and decrements on completion, then check `worker.inFlightRequests === 0` before cleanup/termination.

Applied to files:

  • docs/guide/runtimes/node.md
🪛 GitHub Actions: CI
test/integration.test.ts

[error] 121-121: AssertionError: expected 0 to be 0? actually received 2. Test 'generate() emits valid TypeScript for advanced typing fixtures' failed. Expected compile.code to be 0 but got 2.

🪛 GitHub Check: test (20, 3.10)
test/integration.test.ts

[failure] 121-121: test/integration.test.ts > IR-only integration > generate() emits valid TypeScript for advanced typing fixtures
AssertionError: expected 2 to be +0 // Object.is equality

  • Expected
  • Received
  • 0
  • 2

❯ test/integration.test.ts:121:28

🪛 GitHub Check: test (22, 3.10)
test/integration.test.ts

[failure] 121-121: test/integration.test.ts > IR-only integration > generate() emits valid TypeScript for advanced typing fixtures
AssertionError: expected 2 to be +0 // Object.is equality

  • Expected
  • Received
  • 0
  • 2

❯ test/integration.test.ts:121:28

🔇 Additional comments (44)
docs/reference/cli.md (1)

1-129: LGTM!

The CLI reference is comprehensive, covering both commands with their flags, exit codes, and a helpful starter config example. The flags table for tywrap generate now includes all supported options.

.github/labeler.yml (1)

26-33: Minor redundancy in docs patterns (previously noted).

Lines 31-33 (CONTRIBUTING.md, AGENTS.md, CLAUDE.md) are already covered by the *.md glob on line 30. These explicit entries are redundant but harmless—they may serve as documentation of important files.

test/generator.test.ts (1)

221-227: LGTM!

The updated assertion correctly validates that when a function has both varArgs and kwArgs parameters without required keyword-only params, the generator skips intermediate overloads and only emits the full implementation signature. This aligns with the overload generation logic in generator.ts (line 278 condition).

docs/public/llms.txt (1)

1-29: LGTM!

The llms.txt file provides a well-structured index for AI coding agents with clear categorization of documentation resources. The docs and optional sections appropriately prioritize essential guides over supplementary materials.

docs/guide/getting-started.md (1)

1-376: LGTM!

The getting started guide provides comprehensive coverage of installation, configuration, generation, and usage patterns. The formatting improvements enhance readability without changing the technical content.

src/core/generator.ts (3)

120-120: Good: Using globalThis.Array.isArray for cross-realm safety.

This change ensures reliable array detection even when values originate from different JavaScript realms (e.g., iframes, VMs).


278-278: LGTM!

The tightened condition correctly skips overload generation when varArgsParam or needsKwargsParam are present. This prevents emitting invalid TypeScript signatures where rest parameters would conflict with trailing kwargs.


370-370: Consistent use of globalThis.Array.isArray across all call preludes.

The change is applied uniformly to function wrappers (line 370), class methods (line 596), and constructors (line 783), ensuring consistent cross-realm array detection throughout generated code.

Also applies to: 596-596, 783-783

src/core/annotation-parser.ts (5)

43-71: Well-structured helper for parsing typing factory names.

The parseTypingFactoryName function correctly handles:

  • Multiple module prefixes (typing, typing_extensions, collections.abc)
  • Quoted string arguments with proper quote matching
  • Arguments with trailing commas (e.g., TypeVar('T', bound=int))

This cleanly extracts the name from factory calls like TypeVar('T').


73-90: Good refactor: matchBracketedAlias reduces duplication.

This helper consolidates the pattern matching for bracketed type aliases (Optional[T], Sequence[T], etc.) across all module prefixes. The return of both alias name and inner content enables context-aware handling downstream.


231-248: Correct handling of inferred type variables and ParamSpec components.

  • ~T patterns are correctly mapped to typevar kind
  • P.argslist[Any] and P.kwargsdict[str, Any] are reasonable runtime approximations for ParamSpec components

283-331: Comprehensive alias handling for collection and async types.

The new parsing branches correctly map:

  • Sequence[T]list collection
  • Mapping[K, V]dict collection
  • Iterator/Iterable/AsyncIterator/AsyncIterable → generic types
  • Awaitable[T]Promise<T>
  • Coroutine[T, Y, R]Promise<R> (extracts return type)

These mappings align well with TypeScript equivalents.


371-396: Improved Callable parsing handles edge cases.

The enhanced parsing correctly handles:

  • Callable[..., R] with ellipsis for any arguments
  • Callable[[T1, T2], R] with explicit parameter lists
  • Malformed inputs default to ellipsis parameter (defensive)
src/core/mapper.ts (4)

105-114: LGTM! Proper handling of variable-length tuple syntax.

The ellipsis check correctly identifies tuple[T, ...] Python syntax and maps it to Array<T> in TypeScript, which is the idiomatic representation for variable-length homogeneous tuples.


279-284: LGTM! Sound fallback for unsupported typing constructs.

Degrading typing and typing_extensions placeholders to unknown prevents undeclared TypeScript identifiers (like T, P, Ts) from leaking into generated code. The comment clearly explains the rationale.


331-337: LGTM! Return type change aligns with the type system.

The return type change from TSCustomType to TSPrimitiveType is correct since unknown is a primitive type. This is consistent with the TypescriptType union in src/types/index.ts where TSPrimitiveType is a valid member.


468-473: LGTM! Pydantic preset follows established pattern.

The pydantic preset mapping for BaseModel to recordObject follows the same structure as other presets (pandas, scipy, torch, sklearn) and correctly reuses the recordObject defined at the top of mapPresetType.

package.json (2)

74-78: LGTM! Documentation scripts are well-structured.

The docs workflow scripts follow a logical pattern: docs:sync-llms generates AI-discoverable docs, docs:build ensures sync before build, and the standard VitePress dev/preview scripts are included.


157-160: Document the purpose of the @types/react and @types/prop-types overrides.

The @types/react@^18.3.0 override resolves a peer dependency conflict from @docsearch/react (an Algolia dependency of VitePress) which requires @types/react <19. Pinning to ^18.3.0 prevents resolution conflicts when projects upgrade to @types/react@19. Add a comment in package.json explaining this dependency constraint for future maintainers.

			> Likely an incorrect or invalid review comment.
docs/guide/configuration.md (2)

3-16: LGTM! Improved table formatting and field descriptions.

The top-level fields table is now properly aligned with consistent column widths and clearer descriptions.


568-574: LGTM! Links updated for VitePress site structure.

The absolute URL paths (/troubleshooting/, /guide/runtimes/node, /examples/, /reference/api/) are correct for a VitePress deployment and follow the site navigation structure.

src/index.ts (1)

10-10: LGTM! Public API extended with resolved config type.

Exporting ResolvedTywrapConfig alongside TywrapConfig allows consumers to type-safely work with fully resolved configurations, improving the developer experience for programmatic API usage.

test/mapper.test.ts (2)

112-119: LGTM! Test validates pydantic preset behavior.

The test correctly verifies that with the pydantic preset enabled, pydantic.BaseModel maps to an object type (the recordObject shape).


121-153: LGTM! Comprehensive coverage for TypeVar-to-unknown mapping.

The test covers three important cases:

  1. Direct typevar kind → unknown primitive
  2. Custom type from typing module → unknown primitive
  3. Callable with TypeVar return type → function with unknown return

This ensures undeclared TypeScript identifiers won't leak into generated code.

docs/reference/env-vars.md (2)

65-86: LGTM! Clear documentation of configuration approaches.

The section correctly explains that Python executable and virtual environment are configured via code or config files rather than environment variables, with practical examples for both approaches.


10-15: 🧹 Nitpick | 🔵 Trivial

Consider documenting tolerant parsing behavior for numeric variables.

Based on learnings, TYWRAP_CODEC_MAX_BYTES=1024abc is accepted as 1024 (tolerant parsing). Users might benefit from knowing this behavior to avoid confusion when debugging.

📝 Suggested addition to table notes
 | Variable                   | Scope         | Default | Purpose                                                                        |
 | -------------------------- | ------------- | ------- | ------------------------------------------------------------------------------ |
 | `TYWRAP_CODEC_FALLBACK`    | Python bridge | unset   | Set to `json` to allow JSON fallback when Arrow encoding is unavailable        |
-| `TYWRAP_CODEC_MAX_BYTES`   | Python bridge | unset   | Reject response payloads larger than this byte count                           |
-| `TYWRAP_REQUEST_MAX_BYTES` | Python bridge | unset   | Reject request payloads larger than this byte count                            |
+| `TYWRAP_CODEC_MAX_BYTES`   | Python bridge | unset   | Reject response payloads larger than this byte count (parsed tolerantly)       |
+| `TYWRAP_REQUEST_MAX_BYTES` | Python bridge | unset   | Reject request payloads larger than this byte count (parsed tolerantly)        |
⛔ Skipped due to learnings
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:37.032Z
Learning: In tywrap (src/runtime/bridge-core.ts and similar), environment variable parsing follows a tolerant/best-effort policy. For example, `TYWRAP_CODEC_MAX_BYTES=1024abc` should be accepted as 1024. Only reject clearly invalid values (non-numeric start or <=0). This avoids surprising failures from minor typos.
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: runtime/python_bridge.py:99-123
Timestamp: 2026-01-19T21:49:05.612Z
Learning: In the tywrap repository, TYWRAP_REQUEST_MAX_BYTES uses strict integer parsing that rejects values with trailing characters (e.g., "1024abc"). This differs from TYWRAP_CODEC_MAX_BYTES, which uses tolerant/best-effort parsing that accepts numeric prefixes. The strict policy for REQUEST_MAX_BYTES ensures explicit integer values and consistent parse behavior across Node/Python implementations.
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In the tywrap repository, bridges currently use implicit ready detection: the first successful response from the Python subprocess proves the bridge is ready to handle requests.
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:168-172
Timestamp: 2026-01-20T16:00:49.738Z
Learning: In the tywrap project's BridgeProtocol SafeCodec implementation, Arrow format decoders can produce NaN/Infinity values from binary representations even when the raw JSON payload doesn't contain them. This is why validation for special floats must occur both before encoding (to reject invalid inputs) and after applying decoders (to catch values introduced during Arrow deserialization), protecting downstream consumers from unexpected NaN/Infinity values.
docs/reference/type-mapping.md (3)

1-68: LGTM! Comprehensive and accurate type mapping reference.

The documentation accurately reflects the implementation in src/core/mapper.ts:

  • Primitives, collections, unions, and callables are correctly documented
  • Special names section properly documents TypeVar/ParamSpec → unknown behavior
  • Tables are well-formatted and easy to scan

93-98: LGTM! Pydantic preset documentation with runtime context.

Good inclusion of the runtime serialization note (model_dump(by_alias=True, mode='json')), which helps users understand both the static type and runtime behavior.


143-153: LGTM! Clear documentation of mapping limitations.

The "Limits and Fallbacks" section accurately explains the constraints:

  • TypeVar lowering rationale
  • Annotated metadata stripping
  • Runtime vs static type differences

This sets appropriate expectations for users.

test/worker-pool.test.ts (1)

931-957: LGTM! Comprehensive test for background worker replacement.

The test correctly verifies the new replacement behavior: when a worker times out, the pool disposes the old transport, creates a replacement, and maintains the correct worker count. The setTimeout(resolve, 0) allows the async replacement to complete before assertions.

test/annotation-parser.test.ts (1)

75-106: 🛠️ Refactor suggestion | 🟠 Major

Add coverage for bare Callable[P, T] from the advanced fixture.

test/fixtures/python/advanced_types.py uses Callable[P, T], but this block only exercises the factory forms and typing.Callable[~P, ~T]. That lets these unit tests stay green while the new end-to-end fixture still fails to compile. Add assertions for the exact fixture spelling here so regressions fail closer to source.

⛔ Skipped due to learnings
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: test/fixtures/out_of_order_bridge.py:29-48
Timestamp: 2026-01-19T21:00:52.689Z
Learning: Policy for adversarial test fixtures: adversarial fixtures must preserve the failure mode they exercise, even if that behavior would be "bad" in real code. When reviewing test fixtures with unusual patterns (e.g., missing error handling, intentional protocol violations, unanswered requests), ask for clarifying comments about the intent rather than suggesting normalization or fixes.
README.md (5)

6-10: LGTM! New badges improve project visibility.

The added Coverage, npm downloads, PRs Welcome, and Docs badges provide useful project health indicators and encourage community engagement.


26-35: LGTM! Feature comparison table is well-structured.

The "Why tywrap?" comparison table clearly highlights differentiators against alternatives (pythonia, node-calls-python, pymport) and helps users quickly assess fit.


71-72: LGTM! Star CTA is appropriately placed.

The star call-to-action is non-intrusive and positioned well after the Quick Start section.


87-99: LGTM! Runtime bridge notes are clarified.

The updated notes about NodeBridge vs OptimizedNodeBridge and environment inheritance (inheritProcessEnv, TYWRAP_CODEC_MAX_BYTES, TYWRAP_REQUEST_MAX_BYTES) are consistent with the code behavior documented in the retrieved learnings.


141-142: LGTM! Documentation links migrated to external URLs.

All documentation links now point to the hosted docs site at bbopen.github.io/tywrap, consistent with the VitePress docs deployment added in this PR.

Also applies to: 165-168

src/runtime/worker-pool.ts (3)

42-48: LGTM! Well-documented callback for replacement workers.

The onReplacementWorkerReady callback allows callers to distinguish between initial worker readiness and background replacement worker readiness, enabling separate warmup/publish strategies without charging latency to normal requests.


405-430: LGTM! Background replacement worker scheduling is well-implemented.

The implementation correctly:

  • Guards against non-ready state and maxWorkers limit
  • Tracks pendingCreations to prevent over-spawning during concurrent removals
  • Falls back to onWorkerReady when onReplacementWorkerReady is not provided
  • Calls release(worker) to wake queued waiters after the replacement is ready
  • Silently ignores background creation failures (appropriate for proactive replacement)
  • Uses Math.max(0, ...) defensively in finally to ensure counter stays non-negative

Based on learnings, prioritizing core functionality over edge cases with diagnostic-only impact is appropriate here.


464-469: LGTM! Guard against disposal during worker creation.

This check prevents leaking partially-created workers when the pool is torn down mid-creation. The transport is properly disposed before throwing.

docs/guide/runtimes/node.md (5)

20-27: LGTM! Clear bridge selection guidance.

Good clarification that OptimizedNodeBridge is experimental and not part of public API exports, with appropriate reference to ROADMAP.md for unification plans.


80-84: LGTM! Important distinction between config file and constructor options.

Clearly separating tywrap.config.* (wrapper generation) from new NodeBridge(...) (runtime subprocess control) helps users understand the layered configuration model.


120-139: LGTM! Configuration table matches actual interface.

The documented options, types, and defaults align with the NodeBridgeOptions interface in src/runtime/node.ts. Deprecation notes for legacy fields (maxIdleTime, maxRequestsPerProcess, enableJsonFallback, maxLineLength) are appropriately flagged.


238-267: LGTM! Environment variable approach for JSON fallback and payload limits.

Documenting TYWRAP_CODEC_FALLBACK=json, TYWRAP_CODEC_MAX_BYTES, and TYWRAP_REQUEST_MAX_BYTES aligns with the tolerant env-var parsing policy in bridge-core and provides clear guidance on payload control. Based on learnings, the env-var approach avoids surprising failures from minor typos.


623-628: LGTM! Next steps use root-relative paths.

Using root-relative paths (/guide/configuration, /examples/, /troubleshooting/, /reference/api/) is appropriate for the VitePress docs site structure.

Comment thread docs/reference/api/index.md
Comment on lines +78 to +86
const sections = [];
for (const file of orderedDocs) {
const text = await readFile(file, 'utf8');
sections.push(`<!-- Source: ${file} -->\n${text.trimEnd()}\n`);
}

const output = `${header}${sections.join('\n---\n\n').trimEnd()}\n`;
await writeFile('docs/public/llms-full.txt', output, 'utf8');
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding error handling for file I/O operations.

The readFile and writeFile calls in the aggregation loop will throw unhandled rejections if any file operation fails. Adding a try/catch with a descriptive error message would improve debugging when docs are missing or unreadable.

♻️ Optional: wrap I/O in try/catch
+  try {
   const sections = [];
   for (const file of orderedDocs) {
     const text = await readFile(file, 'utf8');
     sections.push(`<!-- Source: ${file} -->\n${text.trimEnd()}\n`);
   }

   const output = `${header}${sections.join('\n---\n\n').trimEnd()}\n`;
   await writeFile('docs/public/llms-full.txt', output, 'utf8');
+  } catch (err) {
+    throw new Error(`Failed to generate llms-full.txt: ${err.message}`);
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/generate-llms-full.mjs` around lines 78 - 86, Wrap the file I/O in a
try/catch around the loop and final write so readFile and writeFile errors are
handled: iterate over orderedDocs inside a try block, catch and log a
descriptive error (including the filename and the caught error) when a readFile
fails while building sections, and similarly catch and log/write a thrown error
when writing the final output (output/header/sections). Ensure the catch
rethrows or exits appropriately for your script (so failures are visible), and
reference the variables/functions sections, orderedDocs, readFile, writeFile,
header, and output when adding the error handling.

Comment thread src/core/generator.ts
Comment on lines +983 to 986
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(c.name)) {
return 'unknown';
}
return c.name;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Silent fallback to unknown may hide invalid type names.

When a custom type name doesn't match the valid TS identifier pattern, the code silently returns 'unknown'. Per the context snippet from mapper.ts, qualified names like "pandas.DataFrame" are normalized to extract the leaf name, but if normalization fails or edge cases arise, the fallback happens silently.

Consider emitting a warning via a diagnostics hook (similar to onUnknownTypeName in annotation-parser) so users can identify when their Python types aren't mapping correctly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/generator.ts` around lines 983 - 986, The current fallback that
returns the literal 'unknown' when a custom type name fails the TS identifier
regex should emit a diagnostic instead of failing silently: in the function that
performs this normalization (the block that tests /^[A-Za-z_$][A-Za-z0-9_$]*$/
and returns c.name or 'unknown'), call the diagnostics hook (e.g.,
onUnknownTypeName) with the original candidate name and the fallback value, then
return the fallback; include context like the raw input and the normalized/leaf
name so users can see what failed. Locate this logic in generator.ts (the
identifier-validation branch) and wire in the same diagnostics hook used by
annotation-parser (onUnknownTypeName) or the existing diagnostics mechanism so
warnings are produced when the fallback is used.

Comment thread src/runtime/node.ts
Comment on lines +634 to +659
async function executeWorkerCall(
worker: PooledWorker,
request: WorkerCallSpec,
timeoutMs: number,
messages: WorkerCallErrorMessages
): Promise<unknown> {
const requestId = generateWarmupId();
let message: string;
try {
message = JSON.stringify({
id: requestId,
protocol: PROTOCOL_ID,
method: 'call',
params: {
module: request.module,
functionName: request.functionName,
args: request.args,
kwargs: {},
},
});
} catch (error) {
throw new BridgeExecutionError(
`${messages.label} failed to encode request: ${error instanceof Error ? error.message : String(error)}`,
{ cause: error instanceof Error ? error : undefined }
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reject Map/Set warmup arguments before building the JSON request.

executeWorkerCall() serializes user-supplied warmup args directly. Map and Set collapse during JSON.stringify(), so a bad warmup config can produce confusing Python-side behavior instead of a deterministic bridge error. Add the same boundary check the main bridge protocol uses before this envelope is encoded.

Based on learnings, in the BridgeProtocol implementation (tywrap), reject Map and Set explicitly before serialization with a clear error like "Bridge protocol does not support Map/Set values".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/runtime/node.ts` around lines 634 - 659, In executeWorkerCall, detect and
reject any Map or Set inside the warmup arguments before building the JSON
envelope: inspect request.args (and any nested values) and throw a
BridgeExecutionError using the provided messages.label and a clear message like
"Bridge protocol does not support Map/Set values" (preserving the error cause if
available) rather than letting JSON.stringify collapse them; update the code
path around generateWarmupId()/JSON.stringify to run this validation and fail
fast so the bridge protocol never receives Map/Set values.

Comment thread test/integration.test.ts
coderabbitai[bot]
coderabbitai Bot previously requested changes Mar 16, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/guide/configuration.md (1)

333-352: 🧹 Nitpick | 🔵 Trivial

Consider documenting tolerant env-var parsing behavior.

Based on learnings, tywrap uses tolerant/best-effort env-var parsing (e.g., TYWRAP_CODEC_MAX_BYTES=1024abc is accepted as 1024). This behavior might be worth documenting here so users understand partial numeric prefixes are accepted.

📝 Optional documentation addition
 export TYWRAP_CODEC_MAX_BYTES="10485760"  # Max response payload size (bytes)
 export TYWRAP_REQUEST_MAX_BYTES="1048576"  # Max request payload size (bytes)
+
+# Note: Numeric env values use tolerant parsing—leading numeric portions
+# are extracted (e.g., "1024abc" → 1024). Only reject non-numeric starts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guide/configuration.md` around lines 333 - 352, Add a short note in the
Runtime configuration section explaining that environment variables such as
TYWRAP_CODEC_MAX_BYTES, TYWRAP_REQUEST_MAX_BYTES, TYWRAP_MEMORY_LIMIT, etc., are
parsed tolerantly (partial numeric prefixes are accepted, e.g. "1024abc" → 1024)
and that this best-effort behavior applies to numeric env-vars; mention any
limits or expected units (bytes, MB, ms) and recommend validating values if
exact parsing is required.
♻️ Duplicate comments (8)
AGENTS.md (1)

40-83: ⚠️ Potential issue | 🟡 Minor

Add a language tag to the repository tree fenced block.

Line 40 uses an unlabeled code fence, which still triggers markdownlint MD040.

Suggested fix
-```
+```text
 src/
   index.ts            # Public API re-exports
@@
 dist/                 # Compiled TypeScript output (do not edit)
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @AGENTS.md around lines 40 - 83, Update the unlabeled fenced code block in
AGENTS.md (the repository tree block) to include a language tag (e.g., change
the opening "" to "text") so markdownlint MD040 is satisfied; locate the
repository tree block starting with "src/" and modify its opening fence only to
include the language tag while keeping the block contents unchanged.


</details>

</blockquote></details>
<details>
<summary>CLAUDE.md (1)</summary><blockquote>

`40-83`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language tag to the repository tree fenced block.**

Line 40 starts an unlabeled fence; markdownlint MD040 will keep flagging it.

 

<details>
<summary>Suggested fix</summary>

```diff
-```
+```text
 src/
   index.ts            # Public API re-exports
@@
 dist/                 # Compiled TypeScript output (do not edit)
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @CLAUDE.md around lines 40 - 83, The repo tree fenced code block in CLAUDE.md
is unlabeled; change the opening fence from totext so the block is
labeled (e.g., replace the initial before "src/" withtext) and leave the
closing ``` as-is; this will satisfy markdownlint MD040 for the repo tree block.


</details>

</blockquote></details>
<details>
<summary>.github/labeler.yml (1)</summary><blockquote>

`29-33`: _🧹 Nitpick_ | _🔵 Trivial_

**Remove redundant explicit Markdown file patterns.**

`*.md` already matches Lines 31-33, so those entries are unnecessary.

 

<details>
<summary>Optional cleanup</summary>

```diff
 area:docs:
   - changed-files:
       - any-glob-to-any-file:
           - 'docs/**'
           - '*.md'
-          - 'CONTRIBUTING.md'
-          - 'AGENTS.md'
-          - 'CLAUDE.md'
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In @.github/labeler.yml around lines 29 - 33, Remove the redundant explicit
Markdown patterns in the labeler configuration: because the '*.md' glob already
covers 'CONTRIBUTING.md', 'AGENTS.md', and 'CLAUDE.md', delete those specific
entries from the list while keeping 'docs/**' and the '*.md' entry; update the
block that currently contains 'docs/**', '*.md', 'CONTRIBUTING.md', 'AGENTS.md',
'CLAUDE.md' to only include the necessary patterns (e.g., 'docs/**' and '*.md').
```

</details>

</blockquote></details>
<details>
<summary>src/runtime/node.ts (1)</summary><blockquote>

`634-653`: _⚠️ Potential issue_ | _🟡 Minor_

**Reject `Map`/`Set` warmup arguments before request encoding.**

At Line 643, `request.args` is encoded directly; `Map`/`Set` values can degrade during `JSON.stringify`, causing non-deterministic bridge behavior instead of an explicit failure.

<details>
<summary>Proposed fix</summary>

```diff
+function assertNoMapSet(value: unknown): void {
+  const stack: unknown[] = [value];
+  const seen = new Set<unknown>();
+  while (stack.length > 0) {
+    const current = stack.pop();
+    if (!current || typeof current !== 'object') continue;
+    if (current instanceof Map || current instanceof Set) {
+      throw new BridgeExecutionError('Bridge protocol does not support Map/Set values');
+    }
+    if (seen.has(current)) continue;
+    seen.add(current);
+    if (Array.isArray(current)) {
+      for (const item of current) stack.push(item);
+    } else {
+      for (const item of Object.values(current as Record<string, unknown>)) stack.push(item);
+    }
+  }
+}
+
 async function executeWorkerCall(
   worker: PooledWorker,
   request: WorkerCallSpec,
   timeoutMs: number,
   messages: WorkerCallErrorMessages
 ): Promise<unknown> {
   const requestId = generateWarmupId();
+  assertNoMapSet(request.args);
   let message: string;
```
</details>




```shell
#!/bin/bash
rg -n -C3 "executeWorkerCall|JSON.stringify|Map/Set values|Bridge protocol does not support Map/Set values" src/runtime/node.ts src/runtime/safe-codec.ts
```

Based on learnings, in tywrap bridge serialization boundaries should reject `Map`/`Set` explicitly before serialization with a deterministic error.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@src/runtime/node.ts` around lines 634 - 653, The warmup payload encodes
request.args directly with JSON.stringify in executeWorkerCall, which will
silently degrade Map/Set values; add an explicit pre-encoding check that walks
request.args and request.kwargs (from the WorkerCallSpec) and rejects any Map or
Set (including nested occurrences) before the JSON.stringify call, throwing a
clear error using the worker call error path (e.g., via WorkerCallErrorMessages
or a thrown Error) so the bridge fails deterministically instead of producing
non-deterministic serialized output.
```

</details>

</blockquote></details>
<details>
<summary>docs/guide/runtimes/comparison.md (1)</summary><blockquote>

`28-37`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language identifier to the decision-guide code fence.**

Use an explicit fence language (for example `text`) to avoid markdown lint warnings and improve accessibility.

 
<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 Do you need subprocess-based Python execution?
 ├── Yes → Does your environment support subprocess?
 │   ├── Node.js or Bun → Use NodeBridge (import from 'tywrap/node' or 'tywrap')
 │   ├── Deno (local) → Use NodeBridge with --allow-run=python3
 │   └── Deno Deploy / serverless → Continue ↓
 └── No (browser, edge, serverless) →
     ├── Can you load ~50MB WebAssembly? → Use PyodideBridge
     └── Need heavy Python libs or can't load WASM → Use HttpBridge
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/guide/runtimes/comparison.md around lines 28 - 37, Add an explicit
language identifier to the decision-guide code fence (the fenced block starting
with the ASCII decision tree) so linting and accessibility tools recognize it;
change the opening triple backticks to include a language such as "text" (e.g.,

guide.
docs/guide/runtimes/bun.md (1)

40-43: ⚠️ Potential issue | 🟠 Major

Correct the bunfig.toml distribution claim.

The current wording implies bunfig.toml is shipped by the package; this section should present it as a sample file users create in their own Bun projects.

📝 Proposed fix
 ## bunfig.toml
 
-tywrap ships with a `bunfig.toml` for build and run settings:
+Example `bunfig.toml` you can add to your Bun project for build and run settings:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guide/runtimes/bun.md` around lines 40 - 43, The heading/section "##
bunfig.toml" incorrectly states that tywrap "ships with a `bunfig.toml`"; change
the copy to present it as a sample file users should add to their Bun project
(e.g., "Example `bunfig.toml` for build and run settings" or "Sample
`bunfig.toml` you can add to your Bun project") and remove any wording that
implies the file is distributed by tywrap so readers understand they must create
it themselves.
docs/reference/api/index.md (1)

247-262: ⚠️ Potential issue | 🟡 Minor

Document authoring input as TywrapConfig, not resolved TywrapOptions.

This section currently makes the public input API look stricter than it is (for example, runtime, performance, and development appear mandatory on Line 254–Line 256).

📘 Suggested doc fix
-## Key Types
+## Key Types

 ```ts
-interface TywrapOptions {
+interface TywrapConfig {
   pythonModules: Record<string, PythonModuleConfig>;
   pythonImportPath?: string[];
-  output: OutputConfig;
-  runtime: RuntimeConfig;
-  performance: PerformanceConfig;
-  development: DevelopmentConfig;
+  output?: OutputConfig;
+  runtime?: RuntimeConfig;
+  performance?: PerformanceConfig;
+  development?: DevelopmentConfig;
   types?: TypeMappingConfig;
   debug?: boolean;
 }

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/reference/api/index.md around lines 247 - 262, Update the docs to
present the public input shape as TywrapConfig (not the resolved TywrapOptions)
and make the environment-specific fields optional: change the interface name
from TywrapOptions to TywrapConfig and mark output, runtime, performance, and
development as optional (output?:, runtime?:, performance?:, development?:) so
the doc reflects the actual public API; locate the interface block that defines
TywrapOptions in docs/reference/api/index.md and apply these renames and
optional modifiers.


</details>

</blockquote></details>
<details>
<summary>test/integration.test.ts (1)</summary><blockquote>

`100-122`: _⚠️ Potential issue_ | _🟠 Major_

**Surface `tsc` diagnostics when compile fails.**

The current assertion on Line 121 fails without printing actionable compiler output, which blocks debugging the existing red CI run.

<details>
<summary>🛠️ Suggested fix</summary>

```diff
       const compile = await processUtils.exec(
         process.execPath,
         [
@@
         { cwd: process.cwd(), timeoutMs: 30_000 }
       );

-      expect(compile.code).toBe(0);
-      expect(compile.stderr).toBe('');
+      const diagnostics = [compile.stdout, compile.stderr].filter(Boolean).join('\n');
+      expect(compile.code, diagnostics || 'TypeScript compile failed with no diagnostics').toBe(0);
+      expect(compile.stderr, diagnostics).toBe('');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration.test.ts` around lines 100 - 122, The test currently asserts
compile success but drops tsc output, making failures uninformative; update the
block around processUtils.exec / compile to print or include compiler
diagnostics when compile.code !== 0 by referencing the compile variable returned
from processUtils.exec (and tscPath/generatedPath for context). Concretely, add
a conditional that logs or fails with compile.stderr and compile.stdout (e.g.,
console.error or fail(`tsc failed: ${compile.stderr}\n${compile.stdout}`))
before the expect checks so the diagnostic text is visible when compilation
fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/index.md`:
- Around line 49-51: The blockquote has an extra blank line between the two
quoted lines which triggers markdownlint MD028; remove the empty line so both
lines remain consecutive blockquote lines (each starting with ">"), i.e., make
the lines starting with "⚠️ **Experimental** — APIs may change before v1.0.0..."
and "If tywrap saves you time, a ⭐ on [GitHub]..." contiguous with no blank line
between them to satisfy MD028.

---

Outside diff comments:
In `@docs/guide/configuration.md`:
- Around line 333-352: Add a short note in the Runtime configuration section
explaining that environment variables such as TYWRAP_CODEC_MAX_BYTES,
TYWRAP_REQUEST_MAX_BYTES, TYWRAP_MEMORY_LIMIT, etc., are parsed tolerantly
(partial numeric prefixes are accepted, e.g. "1024abc" → 1024) and that this
best-effort behavior applies to numeric env-vars; mention any limits or expected
units (bytes, MB, ms) and recommend validating values if exact parsing is
required.

---

Duplicate comments:
In @.github/labeler.yml:
- Around line 29-33: Remove the redundant explicit Markdown patterns in the
labeler configuration: because the '*.md' glob already covers 'CONTRIBUTING.md',
'AGENTS.md', and 'CLAUDE.md', delete those specific entries from the list while
keeping 'docs/**' and the '*.md' entry; update the block that currently contains
'docs/**', '*.md', 'CONTRIBUTING.md', 'AGENTS.md', 'CLAUDE.md' to only include
the necessary patterns (e.g., 'docs/**' and '*.md').

In `@AGENTS.md`:
- Around line 40-83: Update the unlabeled fenced code block in AGENTS.md (the
repository tree block) to include a language tag (e.g., change the opening "```"
to "```text") so markdownlint MD040 is satisfied; locate the repository tree
block starting with "src/" and modify its opening fence only to include the
language tag while keeping the block contents unchanged.

In `@CLAUDE.md`:
- Around line 40-83: The repo tree fenced code block in CLAUDE.md is unlabeled;
change the opening fence from ``` to ```text so the block is labeled (e.g.,
replace the initial ``` before "src/" with ```text) and leave the closing ```
as-is; this will satisfy markdownlint MD040 for the repo tree block.

In `@docs/guide/runtimes/bun.md`:
- Around line 40-43: The heading/section "## bunfig.toml" incorrectly states
that tywrap "ships with a `bunfig.toml`"; change the copy to present it as a
sample file users should add to their Bun project (e.g., "Example `bunfig.toml`
for build and run settings" or "Sample `bunfig.toml` you can add to your Bun
project") and remove any wording that implies the file is distributed by tywrap
so readers understand they must create it themselves.

In `@docs/guide/runtimes/comparison.md`:
- Around line 28-37: Add an explicit language identifier to the decision-guide
code fence (the fenced block starting with the ASCII decision tree) so linting
and accessibility tools recognize it; change the opening triple backticks to
include a language such as "text" (e.g., ```text) to avoid markdown-lint
warnings and improve rendering for the decision guide.

In `@docs/reference/api/index.md`:
- Around line 247-262: Update the docs to present the public input shape as
TywrapConfig (not the resolved TywrapOptions) and make the environment-specific
fields optional: change the interface name from TywrapOptions to TywrapConfig
and mark output, runtime, performance, and development as optional (output?:,
runtime?:, performance?:, development?:) so the doc reflects the actual public
API; locate the interface block that defines TywrapOptions in
docs/reference/api/index.md and apply these renames and optional modifiers.

In `@src/runtime/node.ts`:
- Around line 634-653: The warmup payload encodes request.args directly with
JSON.stringify in executeWorkerCall, which will silently degrade Map/Set values;
add an explicit pre-encoding check that walks request.args and request.kwargs
(from the WorkerCallSpec) and rejects any Map or Set (including nested
occurrences) before the JSON.stringify call, throwing a clear error using the
worker call error path (e.g., via WorkerCallErrorMessages or a thrown Error) so
the bridge fails deterministically instead of producing non-deterministic
serialized output.

In `@test/integration.test.ts`:
- Around line 100-122: The test currently asserts compile success but drops tsc
output, making failures uninformative; update the block around processUtils.exec
/ compile to print or include compiler diagnostics when compile.code !== 0 by
referencing the compile variable returned from processUtils.exec (and
tscPath/generatedPath for context). Concretely, add a conditional that logs or
fails with compile.stderr and compile.stdout (e.g., console.error or fail(`tsc
failed: ${compile.stderr}\n${compile.stdout}`)) before the expect checks so the
diagnostic text is visible when compilation fails.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7a603497-67e3-427e-88fa-167b3733f55f

📥 Commits

Reviewing files that changed from the base of the PR and between 30f4a40 and 4942383.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (51)
  • .github/dependabot.yml
  • .github/labeler.yml
  • .github/workflows/ci.yml
  • .github/workflows/docs.yml
  • .github/workflows/labeler.yml
  • .github/workflows/publish.yml
  • .github/workflows/release.yml
  • .github/workflows/stale.yml
  • .gitignore
  • AGENTS.md
  • CLAUDE.md
  • README.md
  • docs/.vitepress/config.ts
  • docs/api/README.md
  • docs/examples/index.md
  • docs/guide/configuration.md
  • docs/guide/getting-started.md
  • docs/guide/runtimes/browser.md
  • docs/guide/runtimes/bun.md
  • docs/guide/runtimes/comparison.md
  • docs/guide/runtimes/deno.md
  • docs/guide/runtimes/http.md
  • docs/guide/runtimes/node.md
  • docs/index.md
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/public/llms-full.txt
  • docs/public/llms.txt
  • docs/reference/api/index.md
  • docs/reference/cli.md
  • docs/reference/env-vars.md
  • docs/reference/type-mapping.md
  • docs/troubleshooting/index.md
  • docs/type-mapping-matrix.md
  • package.json
  • scripts/generate-llms-full.mjs
  • src/config/index.ts
  • src/core/annotation-parser.ts
  • src/core/generator.ts
  • src/core/mapper.ts
  • src/index.ts
  • src/runtime/node.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
  • test/annotation-parser.test.ts
  • test/generator.test.ts
  • test/integration.test.ts
  • test/mapper.test.ts
  • test/type_mapping_edge_cases.test.ts
  • test/type_mapping_enhanced.test.ts
  • test/worker-pool.test.ts
  • tywrap_ir/pyproject.toml
💤 Files with no reviewable changes (3)
  • docs/type-mapping-matrix.md
  • .github/workflows/publish.yml
  • docs/api/README.md
📜 Review details
🧰 Additional context used
🧠 Learnings (16)
📚 Learning: 2026-01-19T21:14:40.872Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-263
Timestamp: 2026-01-19T21:14:40.872Z
Learning: In `src/runtime/bridge-core.ts` and similar hot request/response loop implementations in the tywrap repository, avoid adding extra defensive validation (e.g., runtime shape checks on error payloads) in tight loops unless the protocol boundary is untrusted or there's a concrete bug report. The Python bridge protocol is controlled and validated via tests, so defensive checks would add unnecessary branching overhead without meaningful benefit.

Applied to files:

  • docs/guide/runtimes/comparison.md
  • AGENTS.md
  • docs/guide/runtimes/http.md
  • README.md
  • docs/guide/getting-started.md
  • test/integration.test.ts
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-20T16:01:39.136Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:826-830
Timestamp: 2026-01-20T16:01:39.136Z
Learning: In the tywrap BridgeProtocol architecture (ADR-002), `HttpIO` (and other Transport implementations like `ProcessIO`, `PyodideIO`) implements only the `Transport` interface (methods: `send`, `isReady`, `dispose`). The `RuntimeExecution` interface methods (`call`, `instantiate`, `callMethod`, `disposeInstance`) are implemented by `BridgeProtocol`, which delegates to `Transport` instances. Transport implementations should not include RuntimeExecution methods.

Applied to files:

  • docs/guide/runtimes/comparison.md
  • docs/guide/runtimes/http.md
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In the tywrap repository, bridges currently use implicit ready detection: the first successful response from the Python subprocess proves the bridge is ready to handle requests.

Applied to files:

  • docs/guide/runtimes/comparison.md
  • docs/guide/runtimes/http.md
  • README.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:48:27.823Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: test/runtime_bridge_fixtures.test.ts:59-66
Timestamp: 2026-01-19T21:48:27.823Z
Learning: In fixture-based tests (e.g., test/runtime_bridge_fixtures.test.ts) and similar tests in the tywrap repository, prefer early returns when Python or fixture files are unavailable. Do not rely on Vitest dynamic skip APIs; a silent pass is intentional for environments lacking Python/fixtures. Treat missing fixtures as optional soft-guards and ensure the test remains non-disruptive in non-availability scenarios.

Applied to files:

  • test/type_mapping_edge_cases.test.ts
  • test/integration.test.ts
  • test/mapper.test.ts
  • test/worker-pool.test.ts
  • test/type_mapping_enhanced.test.ts
  • test/annotation-parser.test.ts
  • test/generator.test.ts
📚 Learning: 2026-01-20T01:34:07.064Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:444-458
Timestamp: 2026-01-20T01:34:07.064Z
Learning: When reviewing promise-based polling patterns (e.g., recursive setTimeout in waitForAvailableWorker functions), ensure that any recursive timer is tracked and cleared on timeout or promise resolution to prevent timer leaks. Do not rely on no-op checks after settlement; verify clearTimeout is invoked in all paths and consider using an explicit cancellation (e.g., AbortController) or a guard to cancel pending timers when the promise settles.

Applied to files:

  • test/type_mapping_edge_cases.test.ts
  • src/runtime/node.ts
  • src/config/index.ts
  • test/integration.test.ts
  • src/runtime/pooled-transport.ts
  • test/mapper.test.ts
  • src/core/generator.ts
  • src/index.ts
  • src/core/mapper.ts
  • src/core/annotation-parser.ts
  • test/worker-pool.test.ts
  • test/type_mapping_enhanced.test.ts
  • test/annotation-parser.test.ts
  • test/generator.test.ts
  • src/runtime/worker-pool.ts
📚 Learning: 2026-01-20T18:37:05.670Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: src/runtime/process-io.ts:37-40
Timestamp: 2026-01-20T18:37:05.670Z
Learning: In the tywrap repo, ESLint is used for linting (not Biome). Do not flag regex literals that contain control characters (e.g., \u001b, \u0000-\u001F) as lint errors, since the current ESLint configuration allows them. When reviewing TypeScript files (e.g., src/**/*.ts), rely on ESLint results and avoid raising issues about these specific control-character regex literals unless there is a competing config change or a policy requiring explicit escaping.

Applied to files:

  • test/type_mapping_edge_cases.test.ts
  • src/runtime/node.ts
  • src/config/index.ts
  • test/integration.test.ts
  • src/runtime/pooled-transport.ts
  • test/mapper.test.ts
  • src/core/generator.ts
  • src/index.ts
  • src/core/mapper.ts
  • src/core/annotation-parser.ts
  • test/worker-pool.test.ts
  • test/type_mapping_enhanced.test.ts
  • test/annotation-parser.test.ts
  • test/generator.test.ts
  • src/runtime/worker-pool.ts
📚 Learning: 2026-01-20T16:00:49.829Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:203-211
Timestamp: 2026-01-20T16:00:49.829Z
Learning: In the BridgeProtocol implementation (tywrap), reject Map and Set explicitly before serialization (e.g., in safeStringify or the serialization entrypoint) with a clear error like "Bridge protocol does not support Map/Set values". Do not rely on post-hoc checks of non-string keys at the point of JSON.stringify, since Maps/Sets cannot round-trip. This should be enforced at the boundary where data is prepared for serialization to ensure deterministic errors and prevent invalid data from propagating.

Applied to files:

  • test/type_mapping_edge_cases.test.ts
  • src/runtime/node.ts
  • src/config/index.ts
  • test/integration.test.ts
  • src/runtime/pooled-transport.ts
  • test/mapper.test.ts
  • src/core/generator.ts
  • src/index.ts
  • src/core/mapper.ts
  • src/core/annotation-parser.ts
  • test/worker-pool.test.ts
  • test/type_mapping_enhanced.test.ts
  • test/annotation-parser.test.ts
  • test/generator.test.ts
  • src/runtime/worker-pool.ts
📚 Learning: 2026-01-19T21:14:37.032Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:37.032Z
Learning: In tywrap (src/runtime/bridge-core.ts and similar), environment variable parsing follows a tolerant/best-effort policy. For example, `TYWRAP_CODEC_MAX_BYTES=1024abc` should be accepted as 1024. Only reject clearly invalid values (non-numeric start or <=0). This avoids surprising failures from minor typos.

Applied to files:

  • docs/guide/runtimes/http.md
  • docs/reference/env-vars.md
  • README.md
  • src/config/index.ts
  • docs/reference/api/index.md
  • docs/guide/configuration.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-20T16:01:14.323Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 152
File: docs/adr/002-bridge-protocol.md:599-602
Timestamp: 2026-01-20T16:01:14.323Z
Learning: In `src/runtime/node-bridge.ts` (NodeBridge), a test message is sent to the Python subprocess to confirm the bridge is responsive before marking it as ready.

Applied to files:

  • docs/guide/runtimes/http.md
  • src/runtime/node.ts
  • README.md
  • docs/guide/getting-started.md
  • test/integration.test.ts
  • docs/plans/2026-03-10-tywrap-promotion.md
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:48:45.693Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-298
Timestamp: 2026-01-19T21:48:45.693Z
Learning: In `src/runtime/bridge-core.ts`, keep `normalizeErrorPayload` to validate error payloads from the Python subprocess. The subprocess boundary is effectively untrusted, and normalizing error responses prevents `undefined: undefined` errors on malformed payloads. Error responses are not the hot path, so the small validation overhead is acceptable for the added resilience.

Applied to files:

  • docs/reference/env-vars.md
  • src/runtime/node.ts
  • README.md
  • src/core/generator.ts
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:14:35.390Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:260-263
Timestamp: 2026-01-19T21:14:35.390Z
Learning: In src/runtime/bridge-core.ts and similar hot request/response loop implementations in the tywrap repository, avoid adding extra defensive validation (such as runtime, shape, or error-payload checks) inside tight loops unless the protocol boundary is untrusted or there is a concrete bug report. The Python bridge protocol is controlled via tests, so these checks add unnecessary branching overhead without meaningful benefit. Apply this guidance to other hot-path runtime loops in src/runtime/**/*.ts, and re-enable additional validations only when a documented risk or failure scenario is identified. Ensure tests cover protocol validation where applicable.

Applied to files:

  • src/runtime/node.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
📚 Learning: 2026-01-19T21:00:30.825Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: test/adversarial_playground.test.ts:339-360
Timestamp: 2026-01-19T21:00:30.825Z
Learning: In adversarial tests for the bridge (test/adversarial_playground.test.ts), recovery assertions should be kept in the finally block adjacent to cleanup to verify resilience under stress, even if that means post-timeout checks might mask the original error. The goal is to surface recovery failures as legitimate test failures.

Applied to files:

  • src/runtime/node.ts
  • test/integration.test.ts
  • test/worker-pool.test.ts
📚 Learning: 2026-01-20T01:36:14.701Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:743-759
Timestamp: 2026-01-20T01:36:14.701Z
Learning: In the tywrap repository, when reviewing concurrent request handling patterns (especially with BridgeCore request multiplexing), flag uses of boolean `busy` flags that should be request counters instead. A boolean flag creates a race condition: when request A completes and sets `busy = false`, request B (still in flight via multiplexing) is incorrectly treated as idle. The fix is to use an `inFlightRequests: number` counter that increments on request start and decrements on completion, then check `worker.inFlightRequests === 0` before cleanup/termination.

Applied to files:

  • src/runtime/node.ts
  • docs/guide/runtimes/node.md
📚 Learning: 2026-01-19T21:14:29.869Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: src/runtime/bridge-core.ts:375-385
Timestamp: 2026-01-19T21:14:29.869Z
Learning: In the runtime env-var parsing (e.g., in src/runtime/bridge-core.ts and similar modules), adopt a tolerant, best-effort policy: numeric env values should parse by taking the leading numeric portion (e.g., TYWRAP_CODEC_MAX_BYTES=1024abc -> 1024). Only reject clearly invalid values (non-numeric start or <= 0). This reduces surprising failures from minor typos. Add tests to cover partial numeric prefixes, and ensure downstream logic documents the trusted range; consider a small helper to extract a positive integer from a string with a safe fallback.

Applied to files:

  • src/runtime/node.ts
  • src/runtime/pooled-transport.ts
  • src/runtime/worker-pool.ts
📚 Learning: 2026-01-20T01:33:12.841Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 136
File: src/runtime/node.ts:238-249
Timestamp: 2026-01-20T01:33:12.841Z
Learning: In the tywrap repository, when reviewing init/startup patterns, prioritize cases that break core functionality over edge cases with diagnostic-only impact (e.g., missing bridgeInfo metadata). If workers are healthy and operational, defer low-impact defensive checks to follow-up PRs.

Applied to files:

  • src/runtime/node.ts
  • docs/plans/2026-03-10-tywrap-promotion.md
📚 Learning: 2026-01-19T21:49:05.612Z
Learnt from: bbopen
Repo: bbopen/tywrap PR: 127
File: runtime/python_bridge.py:99-123
Timestamp: 2026-01-19T21:49:05.612Z
Learning: In the tywrap repository, TYWRAP_REQUEST_MAX_BYTES uses strict integer parsing that rejects values with trailing characters (e.g., "1024abc"). This differs from TYWRAP_CODEC_MAX_BYTES, which uses tolerant/best-effort parsing that accepts numeric prefixes. The strict policy for REQUEST_MAX_BYTES ensures explicit integer values and consistent parse behavior across Node/Python implementations.

Applied to files:

  • docs/guide/runtimes/node.md
🪛 GitHub Actions: CI
test/integration.test.ts

[error] 121-121: Test 'generate() emits valid TypeScript for advanced typing fixtures' failed. AssertionError: expected 2 to be +0.

🪛 GitHub Check: test (20, 3.10)
test/integration.test.ts

[failure] 121-121: test/integration.test.ts > IR-only integration > generate() emits valid TypeScript for advanced typing fixtures
AssertionError: expected 2 to be +0 // Object.is equality

  • Expected
  • Received
  • 0
  • 2

❯ test/integration.test.ts:121:28

🪛 GitHub Check: test (22, 3.10)
test/integration.test.ts

[failure] 121-121: test/integration.test.ts > IR-only integration > generate() emits valid TypeScript for advanced typing fixtures
AssertionError: expected 2 to be +0 // Object.is equality

  • Expected
  • Received
  • 0
  • 2

❯ test/integration.test.ts:121:28

🪛 LanguageTool
docs/plans/2026-03-10-tywrap-promotion.md

[uncategorized] ~1250-~1250: The official name of this software platform is spelled with a capital “H”.
Context: ...ep 1: Add the Codecov upload step** In .github/workflows/ci.yml, find the test job....

(GITHUB)

🪛 markdownlint-cli2 (0.21.0)
AGENTS.md

[warning] 40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/index.md

[warning] 50-50: Blank line inside blockquote

(MD028, no-blanks-blockquote)

🔇 Additional comments (48)
.gitignore (1)

51-53: Good addition for docs artifact hygiene.

Ignoring docs/.vitepress/dist/ and docs/.vitepress/cache/ prevents noisy commits from generated docs outputs.

docs/troubleshooting/index.md (1)

647-648: Link migration looks correct.

The updated runtime links match the new guide routing structure and reduce relative-path fragility.

.github/workflows/ci.yml (1)

71-79: Coverage gating strategy is well implemented.

Running coverage on a single matrix cell and uploading only from that cell keeps CI time/cost controlled while preserving coverage reporting.

.github/workflows/labeler.yml (1)

10-16: Permissions and workflow scope look appropriate.

The job keeps privileges minimal while enabling automated labeling on PR updates.

docs/public/llms.txt (1)

10-29: LLM discovery index is clear and well scoped.

The curated links are relevant and aligned with the new docs structure.

src/runtime/pooled-transport.ts (1)

44-48: LGTM! Clean callback wiring for replacement worker readiness.

The new onReplacementWorkerReady callback follows the established pattern of onWorkerReady. The type definition, storage, and forwarding to WorkerPool are correctly implemented.

Also applies to: 86-88, 111-111, 133-133

.github/dependabot.yml (2)

1-22: LGTM! Well-structured Dependabot configuration.

The npm and github-actions ecosystems are properly configured with grouping, weekly schedules, and appropriate PR limits. The consistent labeling with area:ci is good for automation.

Also applies to: 36-50


24-34: Consider adding grouping for pip dependencies.

The pip ecosystem lacks grouping, unlike npm and github-actions. This was already flagged in a previous review.

.github/workflows/release.yml (1)

1-57: LGTM! Well-structured release automation workflow.

The workflow correctly:

  • Gates npm publishing on release_created output
  • Uses environment protection (environment: npm) for the NPM token
  • Publishes with --provenance for supply chain security
  • Runs tests before publishing to catch regressions
.github/workflows/docs.yml (1)

1-52: LGTM! Standard VitePress + GitHub Pages deployment workflow.

Good practices observed:

  • fetch-depth: 0 enables VitePress "last updated" timestamps
  • cancel-in-progress: false prevents partial deployments
  • Proper permissions scoped for Pages deployment
.github/workflows/stale.yml (1)

1-39: LGTM! Well-configured stale management workflow.

The configuration appropriately:

  • Uses shorter timelines for PRs (60+14 days) vs issues (90+30 days)
  • Exempts security, pinned, and contribution-friendly labels
  • Provides helpful messages guiding users on next steps
scripts/generate-llms-full.mjs (2)

54-67: LGTM! Solid order validation logic.

The sync check between orderedDocs and discovered files ensures the aggregation stays consistent. The detailed error message listing both "Missing from order" and "Not found on disk" will help maintainers quickly resolve mismatches.


78-86: Consider adding error handling for file I/O operations.

This concern was already raised in a previous review. Adding a try/catch would provide clearer error messages when specific files fail to read.

tywrap_ir/pyproject.toml (1)

19-19: LGTM! Metadata improvements enhance discoverability.

The expanded keywords and classifiers better describe the package's purpose. The documentation URL correctly points to the new VitePress site deployed by this PR.

Also applies to: 32-34, 40-40

docs/guide/configuration.md (1)

1-574: LGTM! Comprehensive formatting improvements.

The documentation is well-organized with consistent table formatting, properly aligned columns, and clear code examples. The restructured sections and updated links improve navigation.

src/core/annotation-parser.ts (1)

43-411: Expanded typing construct support is well-structured.

The new alias/factory helpers and branch ordering read cleanly and preserve the existing API while broadening parser coverage.

docs/plans/2026-03-10-tywrap-promotion.md (1)

9-9: Keep the actions/stale major version consistent across the plan.

Line 9 specifies actions/stale@v10, but Line 1407 still shows actions/stale@v9.

Suggested fix
-      - uses: actions/stale@v9
+      - uses: actions/stale@v10
#!/bin/bash
rg -n "actions/stale@v" docs/plans/2026-03-10-tywrap-promotion.md

Also applies to: 1407-1409

package.json (1)

75-79: Docs tooling and metadata updates look consistent.

The scripts, homepage, and VitePress dependency changes align cleanly with the new docs workflow.

Also applies to: 112-113, 143-160

src/core/mapper.ts (1)

279-337: The unknown fallback strategy here is a good safeguard.

This avoids generating invalid TypeScript identifiers from unsupported Python typing placeholders.

Also applies to: 468-473

src/runtime/worker-pool.ts (1)

405-430: Background replacement + disposal handling is solid.

The new replacement path and mid-creation disposal guard improve resilience without blocking foreground requests.

Also applies to: 438-469

test/worker-pool.test.ts (1)

931-957: Good regression coverage for timeout-triggered worker replacement.

This test captures the key replacement/disposal invariants and verifies the newly acquired worker source.

docs/examples/index.md (1)

74-79: Updated docs links are aligned with the new route layout.

The path migration in this section is consistent with the guide/reference restructuring.

docs/guide/runtimes/deno.md (1)

3-78: Deno runtime guidance is clear and actionable.

The setup, permissions, and Deno Deploy caveat are documented clearly and match the expected bridge behavior.

test/generator.test.ts (1)

221-226: Good regression guard for overload pruning.

This negative assertion cleanly protects against reintroducing the removed overload shape.

docs/reference/type-mapping.md (1)

1-171: Type-mapping reference is comprehensive and well-structured.

Coverage of core mapping rules, presets, limits, and examples is clear and aligns with the updated typing behavior.

docs/reference/env-vars.md (1)

10-86: Environment variable documentation is accurate and practical.

The variable tables and examples are clear, and the separation between env-configurable vs code-configurable options is helpful.

test/type_mapping_edge_cases.test.ts (1)

271-324: Edge-case expectations now correctly enforce unknown fallback behavior.

These assertions line up with the mapper change for TypeVar/ParamSpec/TypeVarTuple handling.

docs/reference/cli.md (1)

31-100: Comprehensive CLI coverage looks solid.

The flag tables, config resolution order, and CI-oriented --check/exit-code section are clear and actionable.

docs/.vitepress/config.ts (1)

3-84: VitePress configuration is well-structured.

Navigation, sidebar grouping, local search, and GitHub edit-link wiring are consistent with the new docs IA.

test/annotation-parser.test.ts (1)

51-106: Great coverage expansion for advanced annotation forms.

These cases close important gaps around collections.abc aliases and TypeVar/ParamSpec-derived shapes.

src/index.ts (1)

10-10: Good public type-surface update.

Exporting ResolvedTywrapConfig with TywrapConfig improves API discoverability without runtime risk.

test/mapper.test.ts (1)

112-153: Nice regression coverage for advanced mapping cases.

The new assertions around pydantic.BaseModel and TypeVar-like placeholder fallback are precise and useful.

docs/guide/getting-started.md (1)

291-297: Clear CI and navigation guidance improvements.

The updated --check workflow notes and root-relative “Next Steps/Support” links improve first-run and maintenance UX.

Also applies to: 367-375

docs/guide/runtimes/http.md (2)

35-40: Correct the codec default value in the options table.

Line 40 lists the default for codec as "Arrow", but HttpBridgeOptions.codec is an optional configuration object, not a transport-mode default. This could mislead users about configuration behavior.

📝 Suggested fix
-| `codec` | No | Arrow | Codec options |
+| `codec` | No | — | Codec options (validation/serialization settings) |

1-72: LGTM overall — documentation provides clear guidance for HttpBridge usage.

The guide covers installation, setup, options, Arrow transport, environment variables, and security recommendations appropriately. The content aligns with the BridgeProtocol architecture where HttpBridge implements the Transport interface.

src/core/generator.ts (3)

120-120: Good defensive change using globalThis.Array.isArray.

Using globalThis.Array.isArray instead of Array.isArray ensures correct behavior when arrays cross realm boundaries (e.g., iframe, vm contexts). This is a sound defensive pattern for generated runtime code.


983-986: Silent fallback to unknown may hide invalid type names.

When a custom type name doesn't match a valid TypeScript identifier pattern, the code silently returns 'unknown'. This can mask issues where Python types aren't mapping correctly, making debugging difficult for users.

Consider emitting a warning via a diagnostics hook so users can identify when their custom types fail validation.


278-278: This condition is intentional by design. The code explicitly excludes generating positional-drop overloads when varargs or kwargs are present, as documented in the comment at line 233: "generate trailing optional parameter drop variants (exclude *args/**kwargs)".

This approach improves rather than reduces ergonomics: mixing positional-drop overloads with varargs/kwargs creates ambiguous and complex signatures. The test at line 144 validates this behavior—a function with optional parameters plus varargs/kwargs expects only the full signature overload, never a "dropped" variant. The current implementation is correct.

test/type_mapping_enhanced.test.ts (2)

15-63: LGTM — TypeVar tests correctly updated to expect unknown primitive.

The tests consistently validate that all TypeVar variants (basic, bounded, constrained, covariant) map to { kind: 'primitive', name: 'unknown' }. This aligns with the type mapping changes and provides good coverage for the simplified TypeVar handling.


259-264: LGTM — Test correctly validates custom type preservation.

Using (result as any).name is acceptable in tests to access properties when the exact type shape varies. The test correctly verifies that unknown custom types preserve their name and module.

src/config/index.ts (2)

32-40: LGTM — Clean type distinction between partial and resolved config.

Separating TywrapConfig (user-authored partial config) from ResolvedTywrapConfig (fully resolved config) improves API clarity. Users get better type inference when authoring configs with defineConfig(), while internal code benefits from the fully-resolved type guarantee.


203-222: LGTM — Return types correctly updated.

Both createConfig and resolveConfig now return ResolvedTywrapConfig, accurately reflecting that defaults are merged and the config is complete after these calls.

README.md (3)

26-35: Good addition of feature comparison table.

The comparison table clearly differentiates tywrap from alternatives (pythonia, node-calls-python, pymport), highlighting unique features like auto-generated types, browser support, and multi-runtime compatibility.


141-142: LGTM — Configuration link updated to hosted docs.

The configuration guide link now points to https://bbopen.github.io/tywrap/guide/configuration, consistent with the docs site migration.


165-168: LGTM — Documentation links consistently point to hosted site.

All documentation links (Getting Started, Configuration, API Reference, Troubleshooting) now use the bbopen.github.io/tywrap URLs.

docs/guide/runtimes/node.md (3)

18-27: Good bridge selection guidance.

The documentation clearly distinguishes NodeBridge (default, recommended) from OptimizedNodeBridge (experimental, not public API). Referencing ROADMAP.md for the unification plan helps set expectations.


120-139: Comprehensive options table with clear deprecation guidance.

The options table covers all constructor parameters with types, defaults, and descriptions. The deprecation notice for maxIdleTime, maxRequestsPerProcess, enableJsonFallback, and maxLineLength helps users avoid deprecated fields in new code.


246-267: LGTM — Payload limit documentation is accurate.

The documentation correctly describes TYWRAP_CODEC_MAX_BYTES for response limits and TYWRAP_REQUEST_MAX_BYTES for request limits, with explicit error behavior noted. This aligns with the repository's environment variable handling approach. Based on learnings, TYWRAP_REQUEST_MAX_BYTES uses strict integer parsing while TYWRAP_CODEC_MAX_BYTES uses tolerant/best-effort parsing.

Comment thread docs/index.md
Comment on lines +49 to +51
> ⚠️ **Experimental** — APIs may change before v1.0.0. See [CHANGELOG](https://github.com/bbopen/tywrap/blob/main/CHANGELOG.md) for breaking changes.

> If tywrap saves you time, a ⭐ on [GitHub](https://github.com/bbopen/tywrap) helps others find it.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix blockquote spacing to satisfy markdownlint (MD028).

There is a blank line inside the blockquote sequence.

📝 Proposed fix
 > ⚠️ **Experimental** — APIs may change before v1.0.0. See [CHANGELOG](https://github.com/bbopen/tywrap/blob/main/CHANGELOG.md) for breaking changes.
-
 > If tywrap saves you time, a ⭐ on [GitHub](https://github.com/bbopen/tywrap) helps others find it.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
> ⚠️ **Experimental** — APIs may change before v1.0.0. See [CHANGELOG](https://github.com/bbopen/tywrap/blob/main/CHANGELOG.md) for breaking changes.
> If tywrap saves you time, a ⭐ on [GitHub](https://github.com/bbopen/tywrap) helps others find it.
> ⚠️ **Experimental** — APIs may change before v1.0.0. See [CHANGELOG](https://github.com/bbopen/tywrap/blob/main/CHANGELOG.md) for breaking changes.
> If tywrap saves you time, a ⭐ on [GitHub](https://github.com/bbopen/tywrap) helps others find it.
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 50-50: Blank line inside blockquote

(MD028, no-blanks-blockquote)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/index.md` around lines 49 - 51, The blockquote has an extra blank line
between the two quoted lines which triggers markdownlint MD028; remove the empty
line so both lines remain consecutive blockquote lines (each starting with ">"),
i.e., make the lines starting with "⚠️ **Experimental** — APIs may change before
v1.0.0..." and "If tywrap saves you time, a ⭐ on [GitHub]..." contiguous with no
blank line between them to satisfy MD028.

@bbopen bbopen dismissed coderabbitai[bot]’s stale review March 17, 2026 05:26

Stale CodeRabbit review on superseded commit 4942383; current head 18ff997 has green required checks and CodeRabbit status success.

@bbopen bbopen merged commit bab9301 into main Mar 17, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ci Area: CI and automation area:tooling Area: tooling and CLI documentation Improvements or additions to documentation enhancement New feature or request priority:p1 Priority P1 (high) priority:p2 Priority P2 (medium)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants