Skip to content

Selective Path Coercion (100% Public API Coercion implementation)#579

Closed
yamcodes wants to merge 42 commits intocoercionfrom
coercion-public-api
Closed

Selective Path Coercion (100% Public API Coercion implementation)#579
yamcodes wants to merge 42 commits intocoercionfrom
coercion-public-api

Conversation

@yamcodes
Copy link
Owner

@yamcodes yamcodes commented Dec 22, 2025

This is an attempt to implement coercion, this time by relying on 100% public API which makes ArkEnv much, much more reliable (100% reliable) instead of having to compromise on reliability.

Closes #577, clones #576 (re-opened due to branch rename)

Summary by CodeRabbit

Release Notes

  • Breaking Changes

    • Removed boolean keyword from root scope
    • Port keyword now requires numeric input; string parsing moved to coercion layer
  • New Features

    • Automatic coercion of environment variable strings to numbers and booleans ("true"/"false")
    • Support for numeric refinements (ranges, divisors) on coerced values
  • Improvements

    • Refactored coercion to use public ArkType APIs instead of internal ones for improved reliability
  • Documentation

    • Added coercion behavior documentation to README
    • Added design and specification documents for coercion architecture

✏️ Tip: You can customize this high-level summary in your review settings.

yamcodes and others added 30 commits December 21, 2025 02:49
…chema definitions and refinements, and refine various type and regex functionalities.
…ort` to use `parsedNumber`, and integrate `port` into the ArkType scope.
…, and enhance `number` and `boolean` coercion in `arkenv`.
…ransformation, supporting numeric refinements.
…and boolean type coercion and add new playground debug files.
…oerce` utility and remove playground files.
…t coercion from their definitions and from the `type` export, relying on global coercion instead.
…bers, booleans, ranges, and optional properties.
…oolean nodes, improving internal handling and type inference
… boolean types, ensuring correct application order and type handling
…numeric and boolean types, adding warnings for reliance on undocumented ArkType APIs
…e type assertions in the `coerce` function.
…d introduce a PoC for generic path-based coercion.
…schema introspection and data-level coercion, removing reliance on internal APIs and updating documentation.
…arsing keywords and internal ArkType API usage, and simplifying the `port` keyword.
…amples workflow

- Removed the `id-token: write` permission from the `sync-examples.yml` workflow to streamline permissions and enhance security.
…th improved type annotations, null checks, and compatibility fixes.
@changeset-bot
Copy link

changeset-bot bot commented Dec 22, 2025

🦋 Changeset detected

Latest commit: 3a322bc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
arkenv Patch
@repo/keywords Minor
@repo/scope Minor
@arkenv/bun-plugin Patch
@arkenv/vite-plugin Patch
@repo/types Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Dec 22, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
arkenv Ready Ready Preview, Comment Dec 22, 2025 2:29pm

@github-actions github-actions bot added docs Improvements or additions to documentation arkenv Changes to the `arkenv` npm package. example Issues or Pull Requests concerning at least one ArkEnv example. (Found in the `examples/` directory) tests This issue or PR is about adding, removing or changing tests labels Dec 22, 2025
@yamcodes yamcodes changed the title Coercion public api Selective Path Coercion (100% Public API Coercion implementation) Dec 22, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 22, 2025

Open in StackBlitz

npm i https://pkg.pr.new/arkenv@579
npm i https://pkg.pr.new/@arkenv/bun-plugin@579
npm i https://pkg.pr.new/@arkenv/vite-plugin@579

commit: 3a322bc

@arkenv-bot
Copy link
Contributor

arkenv-bot bot commented Dec 22, 2025

📦 Bundle Size Report

Package Size Limit Diff Status
arkenv 1.2 kB 2 kB +68.8%

All size limits passed!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Walkthrough

Refactors the environment variable coercion system to use ArkType's public introspection API (.in.json) instead of internal schema mutations. Introduces a selective path-based coercion utility that identifies numeric and boolean schema targets and applies coercion through a .pipe() workflow, removing internal API dependency.

Changes

Cohort / File(s) Summary
Documentation & Changesets
.changeset/cyan-loops-hear.md, .changeset/humble-lizards-judge.md, .changeset/open-spiders-tan.md
Multiple changeset entries documenting the coercion refactor: transition from global schema transformer to selective path coercion, simplification of keywords (boolean removal, port refinement), and breaking changes to scope and keyword exports.
Coercion Specification & Design
openspec/specs/coercion/spec.md, openspec/changes/archive/2025-12-20-add-coercion/*, openspec/changes/coercion-public-api/*
New comprehensive specification and design documents detailing numeric/boolean coercion requirements, range/divisor support, literal strictness, and refactor from internal to public API approach via pipeline wrapper pattern and .in.json introspection.
Core Coercion Implementation
packages/arkenv/src/utils/coerce.ts, packages/arkenv/src/utils/coerce.test.ts, packages/arkenv/src/utils/index.ts
New coercion utility using public ArkType introspection; includes helper functions (isNumeric, isBoolean, findCoercionPaths, applyCoercion) to identify coercion targets and apply transformations via .pipe() without touching schema internals.
ArkEnv Integration
packages/arkenv/src/create-env.ts, packages/arkenv/ARKTYPE_INTERNALS.md, packages/arkenv/README.md, packages/arkenv/package.json
Integrates coercion into createEnv via runtime type detection; documents ArkType internal API migration; adds "@ark/schema" dev dependency; updates README with coercion behavior examples.
ArkEnv Tests
packages/arkenv/src/create-env.test.ts, packages/arkenv/src/coercion.integration.test.ts, packages/arkenv/src/custom-types.integration.test.ts, packages/arkenv/src/error.integration.test.ts, packages/arkenv/src/type.test.ts
Comprehensive test suite updates: new coercion-focused tests, adjustments to existing tests to pass numeric/boolean inputs (not strings), validation of ranges/divisors, strict literals, and error scenarios.
Keywords & Scope
packages/internal/keywords/src/index.ts, packages/internal/keywords/src/index.test.ts, packages/internal/scope/src/index.ts, packages/internal/scope/src/index.test.ts
Replaces port/boolean morphs with maybeParsedNumber/maybeParsedBoolean for generic parsing; removes boolean from root scope; updates tests to pass numeric values instead of strings.
Configuration & Example Apps
.gitignore, apps/playgrounds/node/.env.example, apps/playgrounds/node/index.ts, examples/basic/.env.example, examples/basic/index.ts
Trims environment variable examples (removes NODE_ENV, DEBUG, ALLOWED_ORIGINS, ZED_ENV); simplifies imports from arkenv (default vs. named); references env properties inline instead of destructuring.

Sequence Diagram

sequenceDiagram
    participant app as App Code
    participant createEnv as createEnv()
    participant coerce as coerce()
    participant introspection as schema.in.json
    participant coercionMap as CoercionMap
    participant applier as applyCoercion()
    participant pipe as type().pipe()
    participant validator as ArkType Validator

    app->>createEnv: createEnv({ schema, env })
    createEnv->>coerce: coerce(schema)
    
    rect rgb(240, 248, 255)
        note over coerce,introspection: Introspection Phase (One-time)
        coerce->>introspection: schema.in.json
        introspection-->>coerce: JSON representation
        coerce->>coerce: findCoercionPaths()
        note over coerce: Traverse JSON, find numeric<br/>& boolean leaf nodes
        coerce->>coercionMap: Collect target paths
    end
    
    alt Coercion paths found
        coerce->>pipe: type('unknown').pipe(...)
        pipe->>applier: Register coercion handler
        
        rect rgb(255, 250, 240)
            note over applier,validator: Data Flow (Runtime)
            app->>pipe: validate(env)
            pipe->>applier: applyCoercion(data)
            applier->>applier: Clone data, traverse<br/>paths via CoercionMap
            applier->>applier: Parse strings to<br/>numbers/booleans
            applier-->>pipe: Coerced data
        end
        
        pipe->>validator: pipe(schema)
        validator-->>pipe: Validation result
    else No coercion needed
        coerce-->>createEnv: Return schema unchanged
    end
    
    pipe-->>createEnv: Result
    createEnv-->>app: env object
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • New coercion utility (coerce.ts): Dense logic for schema introspection, path traversal, and data transformation; requires careful review of findCoercionPaths() and applyCoercion() implementations.
  • Breaking API changes: Removal of boolean from root scope, replacement of port morph, and new exports (maybeParsedNumber, maybeParsedBoolean) need validation across all usage sites.
  • Integration in create-env.ts: Runtime type detection logic and coercion pipeline assembly must align with existing validation flow.
  • Test coverage density: Multiple test files with similar but distinct updates; verify consistency across unit, integration, and spec tests.

Possibly related PRs

Poem

🐰 A rabbit hops through paths of JSON light,
Selecting nodes where numbers hide in sight,
No internal tunnels, just pipes so pure—
Each string transformed, coercion is secure!
From schema's map to validation's door,
Selective paths do what the docs adore!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Selective Path Coercion (100% Public API Coercion implementation)' accurately describes the main change—implementing coercion using only public ArkType APIs, which is the core objective of the PR.
Linked Issues check ✅ Passed All objectives from issue #577 are met: the implementation uses public ArkType introspection (.in.json) for schema introspection, avoids internal APIs, performs selective path-based coercion, and maintains non-destructive transformation of schemas.
Out of Scope Changes check ✅ Passed All changes directly support the Selective Path Coercion objectives: coercion implementation, test coverage, documentation, keyword refactoring for public API alignment, and removal of internal API dependencies.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch coercion-public-api

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.

@yamcodes yamcodes marked this pull request as ready for review December 22, 2025 14:25
@yamcodes
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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

🧹 Nitpick comments (3)
.changeset/humble-lizards-judge.md (1)

1-9: Consider adding migration guidance.

The breaking changes are clearly documented. However, users migrating from the old boolean keyword or port morph may benefit from explicit migration examples showing:

  1. How to replace removed boolean keyword usage
  2. How to handle the port keyword change (if users were relying on string input)
📝 Suggested addition for migration guidance
 * **BREAKING**: The `boolean` keyword has been removed. Universal boolean coercion is now handled by the `arkenv` package.
 * **BREAKING**: The `port` keyword has been changed from a `string -> number` morph to a pure `number` refinement. Numeric coercion is now handled centrally.
 * Added `maybeParsedNumber` and `maybeParsedBoolean` internal morphs to support central coercion.
+
+**Migration:**
+- If using `boolean` keyword directly, use `"boolean"` in your arkenv schema instead.
+- If using `port` keyword with string inputs, these will now be automatically coerced by arkenv before validation.
packages/arkenv/src/utils/coerce.test.ts (1)

59-66: Consider adding a test for root-level boolean coercion.

The root-level primitive test only covers numeric coercion. For completeness, consider adding a test case for root-level boolean schemas.

🔎 Suggested additional test case
it("should work with root-level boolean primitives", () => {
	const schema = type("boolean");
	const coercedSchema = coerce(schema);
	expect(coercedSchema("true")).toBe(true);
	expect(coercedSchema("false")).toBe(false);
});
openspec/changes/archive/2025-12-20-add-coercion/design.md (1)

65-75: Array coercion behavior needs clearer guidance.

Line 75 states that root-level sequences and array elements are "out of scope for automatic string-to-number coercion unless the environment variable is pre-processed into an array." This limitation should be highlighted more prominently in the flow section or as a known limitation upfront, since it may surprise users with array-typed environment variables.

Consider documenting:

  1. How users should structure schemas if they need array element coercion.
  2. Whether future versions will support automatic array element coercion.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6ac9f2d and 3a322bc.

⛔ Files ignored due to path filters (3)
  • examples/with-bun-react/bun.lock is excluded by !**/*.lock
  • examples/with-bun/bun.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • .changeset/cyan-loops-hear.md
  • .changeset/humble-lizards-judge.md
  • .changeset/open-spiders-tan.md
  • .gitignore
  • apps/playgrounds/node/.env.example
  • apps/playgrounds/node/index.ts
  • examples/basic/.env.example
  • examples/basic/index.ts
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
  • openspec/changes/archive/2025-12-20-add-coercion/tasks.md
  • openspec/changes/coercion-public-api/design.md
  • openspec/changes/coercion-public-api/proposal.md
  • openspec/changes/coercion-public-api/specs/coercion-refactor/spec.md
  • openspec/changes/coercion-public-api/tasks.md
  • openspec/specs/coercion/spec.md
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • packages/arkenv/README.md
  • packages/arkenv/package.json
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/utils/index.ts
  • packages/internal/keywords/src/index.test.ts
  • packages/internal/keywords/src/index.ts
  • packages/internal/scope/src/index.test.ts
  • packages/internal/scope/src/index.ts
💤 Files with no reviewable changes (2)
  • examples/basic/.env.example
  • apps/playgrounds/node/.env.example
🧰 Additional context used
📓 Path-based instructions (17)
openspec/changes/*/proposal.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Create proposal.md with sections: Why, What Changes (with BREAKING markers), and Impact

Files:

  • openspec/changes/coercion-public-api/proposal.md
**/*.{ts,tsx,json,md}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Biome for linting and formatting instead of ESLint and Prettier

Files:

  • openspec/changes/coercion-public-api/proposal.md
  • packages/internal/keywords/src/index.test.ts
  • openspec/specs/coercion/spec.md
  • packages/arkenv/package.json
  • packages/arkenv/src/utils/index.ts
  • openspec/changes/coercion-public-api/design.md
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • openspec/changes/archive/2025-12-20-add-coercion/tasks.md
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • openspec/changes/coercion-public-api/tasks.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • openspec/changes/coercion-public-api/specs/coercion-refactor/spec.md
  • packages/internal/scope/src/index.test.ts
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) as the main function for validated environment objects, available as the default export
Use built-in validators (host, port, url, email) from src/types.ts when available instead of custom validation
Use ArkEnvError for environment variable errors, not generic errors
Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern
Use logical grouping for related environment variables in schemas
Use descriptive env...

Files:

  • packages/internal/keywords/src/index.test.ts
  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • packages/internal/scope/src/index.test.ts
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Test individual functions, components, and hooks in isolation with mocked dependencies using the *.test.ts or *.test.tsx suffix
Mock process.env in tests for different scenarios and save/restore original env in beforeEach/afterEach hooks
Use Vitest's describe/it structure in test files
Test edge cases including invalid and missing environment variable values
Use Vitest for testing framework

**/*.test.{ts,tsx}: Use Vitest for unit and integration tests
Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking
Unit tests should execute in less than 100ms per test
Mock external dependencies (clipboard, network, etc.) in unit tests
Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Test component behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API
Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests
Do not test pure styling or CSS classes, library internals (Radix/shadcn), implementation details (hooks, setState, private variables), or visual variants in component tests
Use Testing Library with user-event for real user simulation in component tests
Query by role, name, label, and text (accessibility first) in component tests
Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible
Keep tests fast, deterministic, and parallelizable
Mock at component boundaries (network, time, context)

Files:

  • packages/internal/keywords/src/index.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • packages/internal/scope/src/index.test.ts
openspec/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

openspec/**/spec.md: Include at least one scenario per requirement using #### Scenario: header format with WHEN and THEN bullet points
Use SHALL/MUST for normative requirements rather than should/may unless intentionally non-normative

Files:

  • openspec/specs/coercion/spec.md
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
  • openspec/changes/coercion-public-api/specs/coercion-refactor/spec.md
packages/*/package.json

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Packages in packages/ directory must be published to npm and require changesets for versioning, proper exports, and type definitions

Files:

  • packages/arkenv/package.json
**/package.json

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Use workspace:* protocol for workspace dependencies between packages

Files:

  • packages/arkenv/package.json
{packages,apps,tooling}/**/package.json

📄 CodeRabbit inference engine (.cursor/rules/pnpm.mdc)

When referencing workspace packages in dependencies, use the workspace:* protocol instead of version numbers

Files:

  • packages/arkenv/package.json
packages/arkenv/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/arktype.mdc)

packages/arkenv/**/*.ts: Use ArkType's type() function to define schemas in environment variable definitions
Leverage ArkType's type inference for TypeScript types instead of manual type definitions
Use the scoped $ type system for custom types defined in scope.ts
Keep environment variable schemas readable and TypeScript-like using ArkType syntax
Use union types for enums in ArkType schemas (e.g., "'dev' | 'prod'") instead of separate enum definitions
Leverage ArkType's built-in types (e.g., string.host, number.port) where possible in environment schemas
Convert ArkType validation errors to ArkEnvError for user-friendly error messages that include variable name and expected type

Files:

  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Use barrel exports (index.ts) for package entry points

Files:

  • packages/arkenv/src/utils/index.ts
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
packages/arkenv/src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Main library implementation should be in src/create-env.ts, built-in validators in src/types.ts, error handling in src/errors.ts, and utilities in src/utils.ts

Files:

  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
**/*.integration.test.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.integration.test.{ts,tsx}: Use integration tests with *.integration.test.ts or *.integration.test.tsx suffix to test how multiple units work together without mocking their interactions
Integration tests should verify interactions between multiple units (like components + hooks + services) without mocking their interactions

**/*.integration.test.{ts,tsx}: Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests
Integration tests should focus on component and hook interactions, function composition and data flow, real dependencies between units, and state synchronization across boundaries
Integration tests should execute between 100ms - 2000ms per test
Use *.integration.test.ts suffix to distinguish integration tests from unit tests

Files:

  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
**/README.md

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Document environment requirements in README files

Files:

  • packages/arkenv/README.md
openspec/changes/*/tasks.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Create tasks.md with numbered implementation checklist items as checkboxes (- [ ] format)

Files:

  • openspec/changes/coercion-public-api/tasks.md
openspec/changes/*/specs/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

openspec/changes/*/specs/**/spec.md: Use ## ADDED|MODIFIED|REMOVED|RENAMED Requirements as delta headers in spec.md files under changes
Ensure change proposals contain delta specs for each affected capability under changes/[change-id]/specs/[capability]/spec.md

Files:

  • openspec/changes/coercion-public-api/specs/coercion-refactor/spec.md
{bin,examples,playgrounds}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Console usage is allowed in bin/ and example/playground directories, otherwise treated as warning

Files:

  • examples/basic/index.ts
examples/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

examples/**/*.{ts,tsx}: Ensure examples demonstrate secure default practices
Add examples in the examples/ directory for new functionality, demonstrating real-world usage patterns

Files:

  • examples/basic/index.ts
🧠 Learnings (45)
📓 Common learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use union types for enums in ArkType schemas (e.g., `"'dev' | 'prod'"`) instead of separate enum definitions
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's type inference for TypeScript types instead of manual type definitions
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable errors, not generic errors
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: For breaking changes, always create an OpenSpec proposal first

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
📚 Learning: 2025-11-24T16:05:35.714Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-24T16:05:35.714Z
Learning: Applies to openspec/changes/*/proposal.md : Create proposal.md with sections: Why, What Changes (with BREAKING markers), and Impact

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • openspec/specs/coercion/spec.md
  • packages/arkenv/package.json
  • packages/arkenv/src/utils/index.ts
  • openspec/changes/coercion-public-api/design.md
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • .changeset/cyan-loops-hear.md
  • packages/arkenv/src/error.integration.test.ts
  • openspec/changes/coercion-public-api/specs/coercion-refactor/spec.md
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • openspec/specs/coercion/spec.md
  • packages/arkenv/package.json
  • packages/arkenv/src/utils/index.ts
  • openspec/changes/coercion-public-api/design.md
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • .changeset/open-spiders-tan.md
  • openspec/changes/archive/2025-12-20-add-coercion/tasks.md
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • .changeset/cyan-loops-hear.md
  • packages/arkenv/src/error.integration.test.ts
  • openspec/changes/coercion-public-api/specs/coercion-refactor/spec.md
  • packages/internal/scope/src/index.test.ts
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • .changeset/humble-lizards-judge.md
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use union types for enums in ArkType schemas (e.g., `"'dev' | 'prod'"`) instead of separate enum definitions

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • packages/arkenv/package.json
  • packages/arkenv/src/utils/index.ts
  • openspec/changes/coercion-public-api/design.md
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • .changeset/cyan-loops-hear.md
  • packages/arkenv/src/error.integration.test.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's type inference for TypeScript types instead of manual type definitions

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • packages/arkenv/package.json
  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/README.md
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • .changeset/cyan-loops-hear.md
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/scope.ts : Define custom types in `scope.ts` using ArkType's scoped type system for reusability across schemas

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • packages/arkenv/package.json
  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/utils/coerce.ts
  • .changeset/open-spiders-tan.md
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/internal/scope/src/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • openspec/specs/coercion/spec.md
  • packages/arkenv/package.json
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • packages/internal/scope/src/index.test.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • packages/arkenv/package.json
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to packages/arkenv/src/**/*.ts : Main library implementation should be in `src/create-env.ts`, built-in validators in `src/types.ts`, error handling in `src/errors.ts`, and utilities in `src/utils.ts`

Applied to files:

  • openspec/changes/coercion-public-api/proposal.md
  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.test.{ts,tsx} : Test edge cases including invalid and missing environment variable values

Applied to files:

  • packages/internal/keywords/src/index.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • packages/internal/scope/src/index.test.ts
📚 Learning: 2025-09-10T19:35:18.179Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 136
File: .changeset/vast-bananas-win.md:2-3
Timestamp: 2025-09-10T19:35:18.179Z
Learning: The arkenv package is currently in v0.x.x (pre-1.0) development phase, where breaking changes are acceptable in minor version bumps according to semantic versioning conventions.

Applied to files:

  • packages/arkenv/package.json
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • packages/arkenv/package.json
  • packages/arkenv/src/utils/coerce.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:04:11.901Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/monorepo.mdc:0-0
Timestamp: 2025-11-24T16:04:11.901Z
Learning: packages/arkenv should not depend on other workspace packages; packages/vite-plugin depends on arkenv; apps/www may depend on workspace packages

Applied to files:

  • packages/arkenv/package.json
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use the scoped `$` type system for custom types defined in `scope.ts`

Applied to files:

  • packages/arkenv/package.json
  • packages/arkenv/src/utils/index.ts
  • packages/arkenv/src/utils/coerce.ts
  • .changeset/open-spiders-tan.md
  • packages/arkenv/ARKTYPE_INTERNALS.md
  • openspec/changes/archive/2025-12-20-add-coercion/design.md
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/internal/scope/src/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/index.ts : Use barrel exports (`index.ts`) for package entry points

Applied to files:

  • packages/arkenv/src/utils/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Prefer tree-shakeable exports for better bundling

Applied to files:

  • packages/arkenv/src/utils/index.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Integration tests should focus on component and hook interactions, function composition and data flow, real dependencies between units, and state synchronization across boundaries

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
  • packages/internal/scope/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Integration tests should verify interactions between multiple units (like components + hooks + services) without mocking their interactions

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Use integration tests with `*.integration.test.ts` or `*.integration.test.tsx` suffix to test how multiple units work together without mocking their interactions

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Use *.integration.test.ts suffix to distinguish integration tests from unit tests

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/internal/scope/src/index.test.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest's `describe`/`it` structure in test files

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.test.{ts,tsx} : Mock `process.env` in tests for different scenarios and save/restore original env in `beforeEach`/`afterEach` hooks

Applied to files:

  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/type.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)

Applied to files:

  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/utils/coerce.test.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` as the main function for validated environment objects, available as the default export

Applied to files:

  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/type.test.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/error.integration.test.ts
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable errors, not generic errors

Applied to files:

  • packages/arkenv/src/create-env.test.ts
  • packages/arkenv/src/create-env.ts
  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/error.integration.test.ts
  • packages/internal/scope/src/index.ts
  • apps/playgrounds/node/index.ts
  • examples/basic/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for testing framework

Applied to files:

  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-11-24T16:04:58.629Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.test.{ts,tsx,js,jsx} : Use `import { test, expect } from "bun:test"` for writing tests

Applied to files:

  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.test.{ts,tsx,js,jsx} : Use `bun:test` for unit and integration testing with `test` and `expect` from the built-in test module

Applied to files:

  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory

Applied to files:

  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects

Applied to files:

  • packages/arkenv/src/create-env.test.ts
📚 Learning: 2025-11-24T16:05:35.714Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-24T16:05:35.714Z
Learning: Applies to openspec/changes/*/tasks.md : Create tasks.md with numbered implementation checklist items as checkboxes (- [ ] format)

Applied to files:

  • openspec/changes/archive/2025-12-20-add-coercion/tasks.md
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use built-in validators (host, port, url, email) from `src/types.ts` when available instead of custom validation

Applied to files:

  • packages/arkenv/src/type.test.ts
  • packages/arkenv/src/custom-types.integration.test.ts
  • packages/arkenv/src/error.integration.test.ts
  • packages/internal/scope/src/index.test.ts
  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-12-05T20:33:10.676Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 498
File: apps/playgrounds/node/index.ts:2-2
Timestamp: 2025-12-05T20:33:10.676Z
Learning: ArkType 2.1.28+ supports Standard Schema specification, allowing interoperability with other Standard Schema-compliant validation libraries (e.g., Zod, Valibot) within the same schema definition

Applied to files:

  • openspec/changes/archive/2025-12-20-add-coercion/proposal.md
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking

Applied to files:

  • packages/arkenv/src/utils/coerce.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Prefer `Number.parseInt` over global `parseInt` (`useNumberNamespace` error)

Applied to files:

  • packages/internal/scope/src/index.test.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use PascalCase for type names (e.g., `ArkEnvError`)

Applied to files:

  • examples/basic/index.ts
🧬 Code graph analysis (10)
packages/internal/keywords/src/index.test.ts (1)
packages/internal/keywords/src/index.ts (1)
  • port (37-37)
packages/arkenv/package.json (3)
packages/arkenv/src/index.test.ts (2)
  • arkenv (50-53)
  • vi (65-81)
packages/bun-plugin/src/index.ts (2)
  • cwd (187-241)
  • processEnvSchema (12-37)
packages/vite-plugin/src/index.ts (1)
  • arkenv (49-86)
packages/arkenv/src/coercion.integration.test.ts (2)
packages/arkenv/src/create-env.ts (1)
  • createEnv (36-56)
packages/arkenv/src/type.ts (1)
  • type (3-3)
packages/arkenv/src/create-env.test.ts (2)
packages/arkenv/src/create-env.ts (1)
  • createEnv (36-56)
packages/arkenv/src/index.ts (1)
  • createEnv (13-13)
packages/arkenv/src/create-env.ts (1)
packages/arkenv/src/utils/coerce.ts (1)
  • coerce (172-182)
packages/arkenv/src/utils/coerce.test.ts (2)
packages/arkenv/src/type.ts (1)
  • type (3-3)
packages/arkenv/src/utils/coerce.ts (1)
  • coerce (172-182)
packages/arkenv/src/custom-types.integration.test.ts (1)
packages/arkenv/src/type.ts (1)
  • type (3-3)
packages/arkenv/src/error.integration.test.ts (1)
packages/arkenv/src/errors.test.ts (1)
  • errors (94-106)
apps/playgrounds/node/index.ts (2)
packages/arkenv/src/index.test.ts (4)
  • vi (65-81)
  • vi (25-35)
  • arkenv (50-53)
  • afterEach (4-82)
packages/arkenv/src/array-defaults.integration.test.ts (1)
  • env (14-30)
packages/internal/keywords/src/index.ts (1)
packages/arkenv/src/type.ts (1)
  • type (3-3)
🪛 LanguageTool
openspec/changes/coercion-public-api/proposal.md

[style] ~5-~5: To elevate your writing, try using a synonym here.
Context: ...codebase fragile to ArkType updates and hard to maintain as it requires deep knowled...

(HARD_TO)


[style] ~5-~5: Consider a different adjective to strengthen your wording.
Context: ...tes and hard to maintain as it requires deep knowledge of ArkType's node architectur...

(DEEP_PROFOUND)

⏰ 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). (3)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-build (lts/*)

Comment on lines 47 to 48
# arktype clone
arktype
Copy link
Contributor

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:

# Search for arktype references in common places
rg -n "arktype" --type ts --type js --type json --type yaml --type yml | head -30

Repository: yamcodes/arkenv

Length of output: 86


🏁 Script executed:

# Search for arktype references more broadly
rg -n "arktype" --type ts --type js --type json | head -50

Repository: yamcodes/arkenv

Length of output: 3895


🏁 Script executed:

# Check for shell scripts that might reference arktype cloning
find . -type f \( -name "*.sh" -o -name "*.bash" \) | xargs grep -l "arktype" 2>/dev/null || echo "No shell scripts with arktype"

# Check package.json for any build/setup scripts mentioning arktype
fd "package.json" | xargs grep -A 5 -B 5 '"scripts"' | grep -A 30 "arktype\|clone" | head -40

# Check the actual .gitignore file around lines 45-50
cat -n .gitignore | sed -n '40,55p'

Repository: yamcodes/arkenv

Length of output: 230


🏁 Script executed:

# Check for any documentation about arktype in the repo
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "*.mdx" \) | xargs grep -l "arktype" 2>/dev/null | head -5

# Check for build configuration files
find . -maxdepth 2 -type f \( -name "vite.config.*" -o -name "tsconfig*" -o -name "turbo.json" -o -name ".npmrc" -o -name "pnpm-workspace.yaml" \)

# Check root package.json for any scripts that might generate arktype
cat package.json | grep -A 100 '"scripts"' | head -50

Repository: yamcodes/arkenv

Length of output: 1778


🏁 Script executed:

# Check pnpm-workspace.yaml for monorepo configuration
cat pnpm-workspace.yaml

# Check if arktype appears as a local workspace package
find . -maxdepth 3 -path "*/node_modules" -prune -o -type d -name "arktype" -print

# Check for any introspection files or generated schema files
find . -path "*/node_modules" -prune -o -type f -name "*.in.json" -print 2>/dev/null | head -10

# Look for any reference to "arktype" in coercion-related files
find . -path "*/node_modules" -prune -o -type f \( -name "*coercion*" -o -name "*coerce*" \) -print

Repository: yamcodes/arkenv

Length of output: 937


🏁 Script executed:

# Check the coercion-related files to understand the arktype reference
cat -n packages/arkenv/src/utils/coerce.ts

# Also check the coercion integration test
cat -n packages/arkenv/src/coercion.integration.test.ts | head -60

Repository: yamcodes/arkenv

Length of output: 8829


🏁 Script executed:

# Check if there's a recently created arktype directory
ls -la | grep arktype

# Check git log to see when this gitignore entry was added and any context
git log --oneline -n 20 -- .gitignore

# Check if there are any references to arktype in CI/CD configs
find . -path "*/node_modules" -prune -o -type f \( -name "*.yml" -o -name "*.yaml" -o -name ".github" \) -o -path "*/.github/*" -print 2>/dev/null | head -20

Repository: yamcodes/arkenv

Length of output: 969


🏁 Script executed:

# Check the specific commit that added the arktype gitignore entry
git show 3a322bc --stat | head -40

# Get more details about what files were changed in that commit
git show 3a322bc --name-only | head -30

# Check if there's an arktype directory that was created
git show 3a322bc:.gitignore | tail -10

Repository: yamcodes/arkenv

Length of output: 3498


🏁 Script executed:

# Check if arktype directory exists or was created
test -d arktype && echo "arktype directory exists" || echo "arktype directory does not exist"

# Check the cursor rules file that was added in the commit
cat -n .cursor/rules/arktype.mdc | head -60

Repository: yamcodes/arkenv

Length of output: 1983


🏁 Script executed:

# Check the PR/commit message more thoroughly
git log --format=fuller 3a322bc | head -40

# Check if there's any documentation about this in the changeset files
cat .changeset/*.md 2>/dev/null | grep -i "arktype\|clone" -A 2 -B 2

Repository: yamcodes/arkenv

Length of output: 1211


Remove the arktype gitignore entry—it's unused and misleading.

The implementation uses ArkType's public introspection API (.in.json) to identify coercion targets, not artifact generation or cloning. No arktype/ directory is created, and the entry should not be in .gitignore.

🤖 Prompt for AI Agents
In .gitignore around lines 47 to 48, remove the obsolete "arktype" entry because
the project does not generate or clone an arktype/ directory; update the file by
deleting that line so the gitignore no longer misleadingly ignores "arktype".

Comment on lines 11 to 14
1. **Keywords**: Define `parsedNumber` and `parsedBoolean` in `@repo/keywords` as reusable building blocks that handle string-to-primitive conversion.
2. **Scope**: Keep `number` and `boolean` as standard ArkType types in `@repo/scope` so they remain "constrainable" (supporting ranges, divisors, etc.).
3. **Transformation**: In `createEnv`, use ArkType's `schema.transform()` to walk the fully parsed schema. The transformer identifies numeric and boolean leaf nodes and automatically wraps them in the appropriate coercion morph.

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Documentation has minor inconsistencies with the implementation.

  1. Line 11 mentions parsedNumber and parsedBoolean, but the implementation uses maybeParsedNumber and maybeParsedBoolean.
  2. Line 13 mentions using schema.transform(), but the implementation uses findCoercionPaths() with schema.in.json introspection and .pipe() composition.

Consider updating the documentation to match the actual implementation approach.

🤖 Prompt for AI Agents
In openspec/changes/archive/2025-12-20-add-coercion/proposal.md around lines 11
to 14, the doc references `parsedNumber`/`parsedBoolean` and
`schema.transform()`, but the code uses `maybeParsedNumber`/`maybeParsedBoolean`
and a `findCoercionPaths()` approach that inspects `schema.in.json` and composes
coercions with `.pipe()`; update the text to use the actual symbol names
(`maybeParsedNumber`, `maybeParsedBoolean`) and replace the description of
transformation to describe using `findCoercionPaths()` with `schema.in.json`
introspection and `.pipe()` composition (or alternatively note that the
implementation differs if you intend to keep the doc as-is), and ensure the
Scope line still clarifies that `number` and `boolean` remain constrainable in
`@repo/scope`.

@yamcodes yamcodes changed the base branch from main to coercion December 22, 2025 14:30
@yamcodes
Copy link
Owner Author

Because schema.in.json (and schema.json) returns a generic JsonStructure, TypeScript sees it essentially as any (technically a recursive string | number | boolean | object).

We cannot access properties like .domain or .unit safely - we are forced to perform "runtime checking" (manual type narrowing) to tell TypeScript that this generic JSON object actually has those specific fields.

Sticking to toJsonSchema() relies on the strictly typed JsonSchema interface from @ark/schema, which is the safer, standard-compliant path.

Closing in favor of #578

@yamcodes yamcodes closed this Dec 22, 2025
@yamcodes yamcodes deleted the coercion-public-api branch December 22, 2025 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arkenv Changes to the `arkenv` npm package. docs Improvements or additions to documentation example Issues or Pull Requests concerning at least one ArkEnv example. (Found in the `examples/` directory) tests This issue or PR is about adding, removing or changing tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Schema-Directed Coercion

1 participant