Skip to content

Coercion#569

Merged
yamcodes merged 39 commits intomainfrom
coercion
Dec 23, 2025
Merged

Coercion#569
yamcodes merged 39 commits intomainfrom
coercion

Conversation

@yamcodes
Copy link
Owner

@yamcodes yamcodes commented Dec 20, 2025

Closes #228

Summary by CodeRabbit

  • New Features

    • Automatic environment-variable coercion (strings auto-convert to numbers/booleans by schema; opt-out available)
    • Site banner and documentation pages introducing coercion
  • Breaking Changes

    • Environment must be passed inside an options object when initializing the loader (e.g., { env: ... })
    • Schemas use native number/boolean types and stricter port validation
    • Some example/playground env shapes and keys changed (e.g., DEBUGGING, URL-typed vars)
  • Documentation

    • New coercion guide and examples; legacy morphs page removed

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

Closes #566 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Environment values are now auto-coerced from strings into numbers and
booleans (including number subtypes like ports and epochs).

* **Breaking Changes**
  * The legacy boolean keyword was removed.
* Within the coercion scope, string inputs coerce to number/boolean;
some number constraints (ranges/divisors) do not apply to coerced
numbers — see workarounds.

* **Documentation**
  * Coercion guide, design, spec, and task docs added.

* **Tests**
  * End-to-end coercion integration tests added.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
@changeset-bot
Copy link

changeset-bot bot commented Dec 20, 2025

🦋 Changeset detected

Latest commit: 9cef3a9

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

This PR includes changesets to release 6 packages
Name Type
@arkenv/vite-plugin Minor
arkenv Minor
@repo/keywords Minor
@repo/scope Minor
@arkenv/bun-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 20, 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 10:22pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Implements schema-directed coercion for environment variables and refactors createEnv to accept a config object { env?, coerce? }. Adds a coerce utility that introspects JSON Schema to auto-convert strings to numbers/booleans, updates keywords/scope, and adjusts plugins, examples, tests, and docs. (Breaking API changes noted.)

Changes

Cohort / File(s) Summary
Core coercion implementation
packages/arkenv/src/utils/coerce.ts, packages/arkenv/src/utils/coerce.test.ts, packages/arkenv/src/utils/index.ts
New schema-driven coerce() that introspects schema JSON and applies pre-validation coercion for numbers/booleans; comprehensive tests added and re-exported.
createEnv API refactor
packages/arkenv/src/create-env.ts, packages/arkenv/src/create-env.test.ts
createEnv now accepts ArkEnvConfig { env?, coerce? } (default coerce: true); applies coerce() when enabled; signatures and tests updated.
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
Adds maybeParsedNumber / maybeParsedBoolean; port becomes strict numeric refinement; removes custom boolean from root scope in favor of standard boolean + global coercion; tests adjusted.
Plugin integrations & call sites
packages/vite-plugin/src/index.ts, packages/vite-plugin/src/index.test.ts, packages/bun-plugin/src/index.ts
Plugin call sites updated to pass env as { env: ... } and tests updated to expect the wrapped env shape.
Examples & playgrounds
apps/playgrounds/*, examples/* (e.g., apps/playgrounds/vite/..., examples/with-vite-react/..., examples/basic/index.ts, apps/playgrounds/bun-react/src/env.ts, ...)
Example schemas converted from string-pipe parsers to native number/boolean/unknown; arkenv invocations updated to { env: ... }; example env keys adjusted and example .env files trimmed.
Docs & site content
apps/www/content/docs/arkenv/coercion.mdx, apps/www/content/docs/arkenv/morphs.mdx (removed), apps/www/components/banner.tsx, apps/www/content/docs/vite-plugin/*.mdx, apps/www/content/docs/arkenv/meta.json
Adds coercion docs, removes morphs page, updates banner/navigation and Vite-plugin docs to reflect new schema examples and invocation shape.
Tests across packages
packages/arkenv/src/*.test.ts, packages/internal/*/src/*.test.ts, packages/vite-plugin/src/index.test.ts, tooling/playwright-www/tests/*
Tests updated for native numeric/boolean inputs, createEnv signature change, coercion edge cases (NaN, whitespace, unions, arrays) and docs navigation (morphs → coercion).
Design, specs & tasks
openspec/changes/archive/2025-12-20-*, openspec/changes/archive/2025-12-22-*, openspec/specs/coercion/spec.md, openspec/*
New design docs, proposals, specs, and task lists describing coercion architecture, pipeline-wrapper approach, and implementation details.
Docs/config & metadata tweaks
packages/arkenv/README.md, apps/www/source.config.ts, .github/copilot-instructions.md, packages/bun-plugin/package.json
README and docs updated for coercion and defaults; Twoslash paths and bundle-size thresholds adjusted.
Changesets
.changeset/*.md
Changesets added documenting breaking API changes (createEnv/arkenv invocation shape, coercion opt-out/config, keyword/scope changes).

Sequence Diagram(s)

sequenceDiagram
    participant User as User code
    participant CreateEnv as createEnv()
    participant Schema as ArkType Schema
    participant Introspect as schema.in.toJsonSchema()
    participant Coerce as coerce() utility
    participant Validate as ArkType validate

    User->>CreateEnv: createEnv(schema, { env, coerce: true })
    CreateEnv->>Schema: parse/compile schema
    CreateEnv->>Introspect: schema.in.toJsonSchema()
    Introspect-->>CreateEnv: JSON Schema metadata
    CreateEnv->>Coerce: create pipeline wrapper when targets found
    User->>Coerce: runtime env (string values)
    Coerce->>Coerce: findCoercionPaths → applyCoercion (numbers / booleans)
    Coerce->>Validate: pass coerced data into original schema
    Validate-->>User: validated, typed env object
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰
I sniffed the env, all strings and light,
I nudged "123" to a number bright,
"false" unspun to boolean true,
The vars now hop in typed shoes,
A rabbit's cheer — the env feels right.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% 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 'Coercion' directly reflects the primary feature added across all changes: automatic coercion of string environment variables into typed primitives (numbers, booleans, etc.).
Linked Issues check ✅ Passed The PR fully addresses issue #228 by implementing centralized coercion. Changes include: new coerce utility for schema-directed coercion [new packages/arkenv/src/utils/coerce.ts], createEnv API update to accept config with coerce option [packages/arkenv/src/create-env.ts], new coercion primitives maybeParsedNumber and maybeParsedBoolean [packages/internal/keywords/src/index.ts], integration across all examples and playgrounds, comprehensive test coverage [coercion.integration.test.ts, create-env.test.ts, utils/coerce.test.ts], and documentation [coercion.mdx, design docs, specs].
Out of Scope Changes check ✅ Passed All changes are directly related to implementing coercion as specified in issue #228. Includes: core coercion implementation, API updates, test updates, documentation, playground/example updates, bundle size constraint updates to support the feature, and playground restructuring (removing unused env vars, adding DEBUGGING). No unrelated changes detected.
✨ 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

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.

@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 20, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 20, 2025

Open in StackBlitz

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

commit: 9cef3a9

@arkenv-bot
Copy link
Contributor

arkenv-bot bot commented Dec 20, 2025

📦 Bundle Size Report

Package Size Limit Diff Status
@arkenv/vite-plugin 1.54 kB 2 kB +73.3%
arkenv 1.41 kB 2 kB +90.7%
@arkenv/bun-plugin 2.06 kB 2.2 kB +43.1%

All size limits passed!

Closes #571 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Environment variables are now auto-coerced from strings to numbers and
booleans during env parsing, including numeric refinements (ranges,
divisors) and strict literal handling. Parsed-number/boolean behavior
applies globally so defaults and dotenv strings become proper
numbers/booleans.

* **Breaking Changes**
  * Legacy boolean keyword renamed to parsedBoolean.
  * number.port now accepts numbers only (string-parsing removed).

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Strengthened type safety and validation in schema coercion utilities,
improving inference and consistency of value transformations and
preserving original structure when possible.
* Improved error detection and messaging for transformation failures and
brittle internal cases.

* **Chores**
* Updated development dependency to support the enhanced internal
handling and more reliable schema processing.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…entation) (#578)

Closes #577 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Breaking Changes**
* Removed the root-level custom boolean keyword; boolean coercion is now
centralized.
* Removed strict parsed-number/boolean variants; numeric/boolean
handling now uses the centralized approach and a stricter numeric
behavior for port-like fields.

* **Improvements**
* Coercion refactored to a schema-driven, pipeline-based pre-processing
step using public introspection.
* Eliminated reliance on undocumented internals for more stable,
reliable coercion and improved performance via one-time introspection.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
- Correctly process `in` schema for coercion
- Add tests for createEnv with morphed schemas
- Add tests for coerce utility with morphed schemas

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Environment variable coercion now correctly handles schemas containing
type transformations and pipes without errors.

* **Documentation**
* Updated schema introspection methodology to explain input-side schema
analysis approach.
  * Added guidance on union handling during coercion.

* **Tests**
* Added comprehensive test coverage for schemas with transformations
across multiple test suites.

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

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Use `toJsonSchema` fallback
- Handle unjsonifiable types
- Preserve base schema structure
- Use public API for introspection

Closes #594 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Improvements**
* Enhanced schema introspection robustness with a fallback mechanism
that preserves base schema structure for types that cannot be fully
represented in standard formats, enabling more resilient coercion
handling.

* **Documentation**
* Updated design and proposal documentation for schema introspection
workflows.

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

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Closes #568 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Chores**
* Updated environment variable validation rules across playgrounds and
examples for improved type consistency.
* Refactored configuration code structure by streamlining variable
declarations and removing intermediate bindings.

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

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added comprehensive coercion documentation explaining automatic type
conversion for environment variables.

* **Documentation**
* Updated documentation structure and navigation to reflect feature
changes.
  * Removed morphs documentation.

* **Breaking Changes**
* Boolean morph feature has been removed; boolean coercion now handled
through standard validation.
  * Port keyword validation enforced to numeric range 0-65535.

* **Chores**
* Renamed DEBUG environment variable to DEBUGGING with updated default
value.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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: 1

🧹 Nitpick comments (5)
packages/arkenv/src/utils/coerce.test.ts (1)

41-48: Consider adding tests for case-insensitive boolean coercion.

The tests verify "true" and "false" coercion, but environment variables are often set with different cases (e.g., "TRUE", "False", "TRUE"). It would be valuable to add tests to document expected behavior for case variations.

🔎 Example additional test cases
it("should handle boolean case variations", () => {
  const schema = type({
    DEBUG: "boolean",
  });
  const coercedSchema = coerce(schema);
  
  // Document expected behavior - either coerce or fail consistently
  const uppercase = coercedSchema({ DEBUG: "TRUE" });
  const mixedCase = coercedSchema({ DEBUG: "True" });
  // Assert expected behavior based on implementation
});
openspec/changes/archive/2025-12-22-coercion-public-api/design.md (4)

28-52: Clarify deduplication strategy and edge cases in union handling.

Two areas need clarification:

  1. Deduplication logic (line 43): The comment states paths are "stringified and deduplicated," but the mechanism isn't detailed. For example:

    • Would ["port"] and ["port", "*"] be treated as different paths (likely correct), or could stringification cause collisions?
    • Are paths deduplicated by exact match, prefix, or both?
  2. Discriminated unions: The design mentions handling anyOf, oneOf, allOf recursively (line 42), but doesn't address discriminated unions (often represented as allOf with a const discriminator). Would these be traversed correctly, or could they generate redundant coercion targets?

Consider adding an example that shows:

  • A nested object with arrays of primitives (e.g., { servers: [{ port: number, enabled: boolean }] }).
  • A discriminated union scenario (if applicable).

54-76: Clarify mutation semantics and edge cases in coercion logic.

Several details about the pre-processing phase need clarification:

  1. In-place mutation (line 68): Is the input object mutated directly, or should it be cloned first? If mutated directly, this could cause issues if the caller reuses the input object. State the design decision explicitly.

  2. Coercion order (lines 69–71): The design attempts maybeParsedNumber first, then maybeParsedBoolean. What's the rationale? For a schema like number | boolean, could a value like "1" be incorrectly coerced to 1 when true might be expected? Consider adding a note on union handling here.

  3. Unconvertible values (line 71): Clarify that leaving unconvertible values as-is (e.g., "abc" remaining a string) is intentional—the validation phase will catch and report the error. This is correct behavior but deserves explicit documentation.

  4. Undefined/null handling: No mention of how undefined or null values in the input are treated. Are they left untouched? Can they be coerced? Add a rule for this.

  5. Pipeline syntax (line 76): The notation type("unknown").pipe(transform).pipe(schema) is introduced but not explained. Briefly clarify what .pipe() does in this context (likely: chains transformations before validation).


78-84: Expand trade-offs section to cover performance and mutation concerns.

The trade-offs section addresses standardization and API stability well, but misses key design decisions:

  1. Performance trade-offs: Discuss whether schema introspection happens at setup time (one-time cost) or runtime (per-call cost). If at setup time, note this as an advantage. If at runtime, explain the performance implications for frequently-used schemas.

  2. Mutation semantics: Explain the trade-off of mutating input data in-place. Benefits: no object cloning overhead. Downsides: caller's input object is modified, which could surprise downstream code. Why was mutation chosen over cloning?

  3. Coercion coverage: The design gracefully handles unjsonifiable refinements by falling back to the base type. Explain the limitation this introduces: custom predicates on number fields will still coerce, but only to the primitive type, not applying the predicate. Is this acceptable?

  4. Comparison to alternatives: The PR objectives mention two approaches were proposed (conversion layer vs. appending .parse). Briefly explain why this design (toJsonSchema() introspection + .pipe()) was chosen over those, or reference where that comparison is documented.

Note: The section appears incomplete (line 84 has a "+ " indicator). Ensure the full trade-offs analysis is included.


1-5: Add user-facing API context to ground the design.

While the design is technically sound and architecturally clear, it jumps directly into implementation details without showing how users interact with coercion. Add a brief introductory section (before or after the Architecture heading) with an example like:

// User creates an env schema and gets automatic coercion
const env = createEnv({
  env: process.env,
  coerce: true  // enables automatic string → typed primitive coercion
})

// PORT: "3000" becomes PORT: 3000 (number)
// DEBUG: "true" becomes DEBUG: true (boolean)

This grounds readers on the user-visible behavior before diving into the pipeline pattern. It also helps validate that the internal design satisfies the stated feature goal.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68956d5 and dd2d649.

📒 Files selected for processing (17)
  • .github/copilot-instructions.md
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/design.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/specs/coercion-refactor/spec.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/tasks.md
  • openspec/changes/archive/2025-12-22-update-hero-videos/design.md
  • openspec/changes/archive/2025-12-22-update-hero-videos/proposal.md
  • openspec/changes/archive/2025-12-22-update-hero-videos/specs/hero-video/spec.md
  • openspec/changes/archive/2025-12-22-update-hero-videos/tasks.md
  • openspec/changes/update-hero-videos/specs/hero-video/spec.md
  • openspec/project.md
  • openspec/specs/coercion-refactor/spec.md
  • openspec/specs/coercion/spec.md
  • openspec/specs/hero-video/spec.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
💤 Files with no reviewable changes (1)
  • openspec/changes/update-hero-videos/specs/hero-video/spec.md
✅ Files skipped from review due to trivial changes (3)
  • openspec/changes/archive/2025-12-22-coercion-public-api/tasks.md
  • openspec/project.md
  • openspec/specs/hero-video/spec.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • openspec/specs/coercion/spec.md
  • openspec/changes/archive/2025-12-20-add-coercion/specs/coercion/spec.md
🧰 Additional context used
📓 Path-based instructions (7)
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/changes/archive/2025-12-22-update-hero-videos/specs/hero-video/spec.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/specs/coercion-refactor/spec.md
  • openspec/specs/coercion-refactor/spec.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/archive/2025-12-22-update-hero-videos/specs/hero-video/spec.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/specs/coercion-refactor/spec.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
  • packages/arkenv/README.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/design.md
  • packages/arkenv/src/utils/coerce.test.ts
  • openspec/specs/coercion-refactor/spec.md
**/README.md

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

Document environment requirements in README files

Files:

  • packages/arkenv/README.md
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/coerce.test.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/arkenv/src/utils/coerce.test.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/arkenv/src/utils/coerce.test.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/coerce.test.ts
🧠 Learnings (31)
📓 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 : 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: .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
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: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use logical grouping for related environment variables in schemas
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 : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type
📚 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: Consider bundle size impact when adding new dependencies - aspirational goal: <1kB gzipped, enforced limit: 2kB gzipped

Applied to files:

  • .github/copilot-instructions.md
📚 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: Keep bundle size small with a goal of < 1kB gzipped

Applied to files:

  • .github/copilot-instructions.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: Always run `pnpm changeset` for version bumps in published packages - never skip changesets

Applied to files:

  • .github/copilot-instructions.md
📚 Learning: 2025-11-29T08:00:08.044Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/pnpm.mdc:0-0
Timestamp: 2025-11-29T08:00:08.044Z
Learning: Applies to pnpm-lock.yaml : Always commit `pnpm-lock.yaml` to version control and never manually edit the lock file. Run `pnpm install` to update it when dependencies change

Applied to files:

  • .github/copilot-instructions.md
📚 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: Applies to packages/*/package.json : Packages in packages/ directory must be published to npm and require changesets for versioning, proper exports, and type definitions

Applied to files:

  • .github/copilot-instructions.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: Avoid breaking changes to the public API without explicit approval and a major version changeset

Applied to files:

  • .github/copilot-instructions.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
📚 Learning: 2025-11-29T08:00:08.044Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/pnpm.mdc:0-0
Timestamp: 2025-11-29T08:00:08.044Z
Learning: Applies to {package.json,pnpm-lock.yaml,pnpm-workspace.yaml} : Always use `pnpm` for all package management operations in this monorepo (never use `npm` or `yarn` commands), except for standalone example projects in the `examples/` folder

Applied to files:

  • .github/copilot-instructions.md
📚 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: Only packages in packages/ directory are published to npm; publishing is handled by changesets using pnpm release

Applied to files:

  • .github/copilot-instructions.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: Use `pnpm install` instead of directly modifying `pnpm-lock.yaml`

Applied to files:

  • .github/copilot-instructions.md
📚 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: Applies to examples/*/package.json : Examples in examples/ directory are not published, may have their own lock files, and are used as test fixtures

Applied to files:

  • .github/copilot-instructions.md
📚 Learning: 2025-11-29T08:00:08.044Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/pnpm.mdc:0-0
Timestamp: 2025-11-29T08:00:08.044Z
Learning: Applies to package.json : Configure only built dependencies (native modules) in `pnpm.onlyBuiltDependencies`, including: biomejs/biome, sentry/cli, swc/core, tailwindcss/oxide, vercel/speed-insights, esbuild, and sharp

Applied to files:

  • .github/copilot-instructions.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/**/spec.md : Include at least one scenario per requirement using #### Scenario: header format with **WHEN** and **THEN** bullet points

Applied to files:

  • openspec/changes/archive/2025-12-22-update-hero-videos/specs/hero-video/spec.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: For MODIFIED requirements, copy the entire existing requirement block and paste under ## MODIFIED Requirements, then edit to reflect new behavior

Applied to files:

  • openspec/changes/archive/2025-12-22-update-hero-videos/specs/hero-video/spec.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 : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • openspec/changes/archive/2025-12-22-coercion-public-api/specs/coercion-refactor/spec.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.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 : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Applied to files:

  • openspec/changes/archive/2025-12-22-coercion-public-api/specs/coercion-refactor/spec.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
  • packages/arkenv/README.md
  • 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: For breaking changes, always create an OpenSpec proposal first

Applied to files:

  • openspec/changes/archive/2025-12-22-coercion-public-api/proposal.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} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern

Applied to files:

  • openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.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/archive/2025-12-22-coercion-public-api/proposal.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
📚 Learning: 2025-12-22T19:44:07.593Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 596
File: examples/basic/index.ts:4-5
Timestamp: 2025-12-22T19:44:07.593Z
Learning: In examples/basic/index.ts: Use explicit ArkType syntax (e.g., "string.ip | 'localhost'", "0 <= number.integer <= 65535") instead of built-in validators (string.host, number.port) to showcase ArkType's type system capabilities for educational purposes.

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.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:

  • packages/arkenv/README.md
📚 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/README.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 : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.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:

  • packages/arkenv/README.md
📚 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/README.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 `ArkEnvError` for environment variable errors, not generic errors

Applied to files:

  • packages/arkenv/README.md
📚 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} : Provide clear, actionable error messages that include the variable name and expected type

Applied to files:

  • packages/arkenv/README.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: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • packages/arkenv/README.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-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/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 **/*.test.{ts,tsx} : Test edge cases including invalid and missing environment variable values

Applied to files:

  • packages/arkenv/src/utils/coerce.test.ts
🧬 Code graph analysis (5)
openspec/changes/archive/2025-12-22-update-hero-videos/specs/hero-video/spec.md (3)
apps/www/components/hero-video.tsx (1)
  • HeroVideo (6-46)
apps/www/app/(home)/page.tsx (1)
  • HomePage (16-108)
apps/www/components/page/video-demo.tsx (1)
  • VideoDemo (15-62)
openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md (2)
packages/arkenv/src/type.test.ts (1)
  • it (4-218)
packages/arkenv/src/create-env.ts (1)
  • createEnv (35-53)
packages/arkenv/README.md (3)
packages/arkenv/src/type.test.ts (4)
  • envType (86-108)
  • envType (132-152)
  • envType (121-130)
  • envType (5-9)
packages/internal/scope/src/index.test.ts (2)
  • envType (33-44)
  • hostType (5-9)
packages/arkenv/src/custom-types.integration.test.ts (4)
  • vi (161-173)
  • vi (129-143)
  • vi (145-159)
  • vi (215-223)
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 (215-238)
openspec/specs/coercion-refactor/spec.md (1)
packages/arkenv/src/type.test.ts (1)
  • it (4-218)
🪛 LanguageTool
openspec/specs/coercion-refactor/spec.md

[grammar] ~4-~4: Use a hyphen to join words.
Context: ...urpose TBD - created by archiving change coercion-public-api. Update Purpose afte...

(QB_NEW_EN_HYPHEN)

⏰ 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). (5)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-typesafety
  • GitHub Check: test-build (lts/*)
  • GitHub Check: test-build (latest)
🔇 Additional comments (14)
openspec/changes/archive/2025-12-22-update-hero-videos/specs/hero-video/spec.md (3)

1-32: Clarify scenario format relative to spec guidelines.

The guidelines specify scenarios should include **WHEN** and **THEN** bullet points, but this file uses the fuller BDD format with Given, When, Then. While the BDD approach is more comprehensive and your scenarios cover the requirement well, confirm with your team whether the extended format is the preferred pattern for all openspec/**/spec.md files, or if a stricter When-Then format is expected for consistency.

Verify guideline interpretation: Should all scenario sections in openspec/ specs use strictly **WHEN** and **THEN** (as written), or is the extended Given-When-Then BDD format acceptable?


3-4: LGTM!

The requirement uses appropriate normative language (MUST) and is clearly stated. The combination of display, behavior, theme-awareness, and responsiveness requirements in a single requirement is cohesive.


29-32: Clarify "gradient overlays" reference.

Scenario 4 mentions handling "interfering gradient overlays," but the HeroVideo component implementation uses opacity-based theme switching without explicit gradient overlay handling. Verify whether:

  • "Gradient overlays" refers to the top gradient overlay SVG shown in HomePage (from the relevant code snippet), which should not interfere with video blending, or
  • The spec should describe the actual mechanism (CSS opacity transitions for theme switching)

This clarification ensures the spec accurately reflects what the component implements.

.github/copilot-instructions.md (1)

284-284: Confirm bundle size measurement for coercion feature before merging. The aspirational goal has been increased from <1kB to <2kB gzipped—verify that actual measurements show the coercion implementation stays within the enforced 2kB limit, and ensure any related documentation updates (README, package.json configuration) are also included if needed.

openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md (1)

1-35: Well-structured proposal with clear technical direction.

The proposal effectively documents the rationale for moving from internal ArkType APIs to the stable schema.in.toJsonSchema() approach. The implementation rules (file size limits, modular organization, strict type safety) align with the project's coding guidelines. Based on learnings, this follows the pattern of creating an OpenSpec proposal for breaking changes.

packages/arkenv/README.md (3)

44-48: Good use of explicit ArkType syntax in the example.

The schema demonstrates ArkType's type system capabilities with "string.ip | 'localhost'", "0 <= number.integer <= 65535", and "boolean = false". This aligns with the educational purpose of the README example.


74-74: Feature list accurately reflects the new coercion capability.

Adding "coerced" to the feature description ("Validated, defaultable, coerced, typesafe environment variables") correctly highlights the new automatic coercion behavior introduced in this PR.


71-71: Bundle size claim of "<2kB gzipped" is correctly documented.

The claim aligns with the project's enforced 2kB size limit (configured in package.json) and reflects the intentional increase from the previous ~700 byte size after adding the coercion feature. This is documented in the recent commit "Adjust bundle size goal to 2KB across documentation" and matches the project guidelines' enforced limit.

packages/arkenv/src/utils/coerce.test.ts (3)

1-4: Clean import structure following project conventions.

Imports are properly organized with external dependencies (arktype, vitest) followed by internal module (./coerce).


195-215: Excellent NaN handling tests.

These tests effectively document the distinction between number.NaN (which accepts NaN) and plain number (which rejects NaN). This is important edge-case coverage that aligns with the coding guidelines for testing edge cases.


216-241: Good array coercion and validation boundary tests.

The tests properly verify that array elements are coerced and that type mismatches (array vs. single value) are correctly rejected by validation. The inline comments help clarify the expected behavior.

openspec/changes/archive/2025-12-22-coercion-public-api/specs/coercion-refactor/spec.md (1)

1-23: Well-structured specification following OpenSpec conventions.

The spec correctly uses MUST for normative requirements and includes properly formatted scenarios with GIVEN/WHEN/THEN structure. The API reference (schema.in.toJsonSchema) aligns with the proposal and actual implementation.

openspec/specs/coercion-refactor/spec.md (1)

6-22: Specification correctly documents the public API approach.

The requirements properly specify the use of schema.in.toJsonSchema (addressing a previous review comment about schema.in.json). The scenarios clearly describe expected behavior for nested paths and pipeline-based coercion.

openspec/changes/archive/2025-12-22-coercion-public-api/design.md (1)

7-26: toJsonSchema() fallback API is correctly specified in the design.

The approach of using schema.in.toJsonSchema({ fallback: (ctx) => ctx.base }) to introspect schemas while preserving resilience against unjsonifiable refinements is valid and aligns with ArkType's public API. The fallback mechanism properly handles base type extraction even when custom predicates or narrows are present.

@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: 1

🧹 Nitpick comments (2)
openspec/specs/coercion/spec.md (1)

4-4: Consider breaking up the long purpose statement.

The purpose statement combines multiple concepts (mechanism definition, archive context, refinements, and literals) in a single complex sentence. Breaking it into separate sentences would improve readability.

🔎 Suggested refactor for clarity
-Define the stable coercion mechanism using public ArkType APIs for environment variable type transformation, documenting goals, scope, and migration guidance following the archive of coercion-public-api. This coercion specifically preserves support for numeric refinements like ranges and divisors while maintaining strictness for numeric literals.
+Define the stable coercion mechanism using public ArkType APIs for environment variable type transformation. This specification documents goals, scope, and migration guidance following the archive of coercion-public-api. The coercion mechanism preserves support for numeric refinements (ranges and divisors) while maintaining strictness for numeric literals.
packages/arkenv/src/utils/coerce.test.ts (1)

221-233: Array coercion test is solid; consider simplifying the comment.

The test correctly validates array element coercion. However, the multi-line comment (lines 223-226) could be more concise since the test itself clearly demonstrates the expected behavior.

🔎 Suggested comment simplification
-	it("should coerce array elements for numeric properties", () => {
-		const schema = type({
-			// Note: The schema expects a "number", but input might be "5" (coerced -> 5)
-			// If input is ["1", "2"], current logic iterates and coerces them to [1, 2]
-			// The validation step will then reject [1, 2] against "number", which is correct behavior.
-			// This test ensures the traversal logic doesn't crash or behave unexpectedly.
-			IDS: "number[]",
-		});
+	it("should coerce array elements for numeric properties", () => {
+		const schema = type({
+			// Coerces array elements ["1", "2", "3"] to [1, 2, 3]
+			IDS: "number[]",
+		});
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd2d649 and a9a7e72.

📒 Files selected for processing (11)
  • apps/playgrounds/vite/vite.config.ts
  • examples/with-vite-react/vite.config.ts
  • openspec/changes/archive/2025-12-02-update-hero-videos/design.md
  • openspec/changes/archive/2025-12-02-update-hero-videos/proposal.md
  • openspec/changes/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.md
  • openspec/changes/archive/2025-12-02-update-hero-videos/tasks.md
  • openspec/changes/archive/2025-12-22-coercion-public-api/design.md
  • openspec/specs/coercion/spec.md
  • packages/arkenv/README.md
  • packages/arkenv/src/utils/coerce.test.ts
  • packages/bun-plugin/package.json
✅ Files skipped from review due to trivial changes (1)
  • packages/bun-plugin/package.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • openspec/changes/archive/2025-12-22-coercion-public-api/design.md
  • packages/arkenv/README.md
🧰 Additional context used
📓 Path-based instructions (8)
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/changes/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.md
  • openspec/specs/coercion/spec.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/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.md
  • examples/with-vite-react/vite.config.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • openspec/specs/coercion/spec.md
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • apps/playgrounds/vite/vite.config.ts
{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/with-vite-react/vite.config.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/with-vite-react/vite.config.ts
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/coerce.test.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/arkenv/src/utils/coerce.test.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/coerce.test.ts
🧠 Learnings (25)
📓 Common learnings
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
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: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use logical grouping for related environment variables in 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 : 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: .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
📚 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: Use ADDED for new standalone capabilities, MODIFIED for changed behavior with full requirement content, and RENAMED for name-only changes

Applied to files:

  • openspec/changes/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.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/*/specs/**/spec.md : Use ## ADDED|MODIFIED|REMOVED|RENAMED Requirements as delta headers in spec.md files under changes

Applied to files:

  • openspec/changes/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.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/**/spec.md : Include at least one scenario per requirement using #### Scenario: header format with **WHEN** and **THEN** bullet points

Applied to files:

  • openspec/changes/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.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: For MODIFIED requirements, copy the entire existing requirement block and paste under ## MODIFIED Requirements, then edit to reflect new behavior

Applied to files:

  • openspec/changes/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.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:

  • examples/with-vite-react/vite.config.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • openspec/specs/coercion/spec.md
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • openspec/specs/coercion/spec.md
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • openspec/specs/coercion/spec.md
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • apps/playgrounds/vite/vite.config.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/with-vite-react/vite.config.ts
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • apps/playgrounds/vite/vite.config.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: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • examples/with-vite-react/vite.config.ts
  • apps/playgrounds/vite/vite.config.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:

  • examples/with-vite-react/vite.config.ts
  • packages/arkenv/src/utils/coerce.test.ts
  • apps/playgrounds/vite/vite.config.ts
📚 Learning: 2025-12-22T19:44:07.593Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 596
File: examples/basic/index.ts:4-5
Timestamp: 2025-12-22T19:44:07.593Z
Learning: In examples/basic/index.ts: Use explicit ArkType syntax (e.g., "string.ip | 'localhost'", "0 <= number.integer <= 65535") instead of built-in validators (string.host, number.port) to showcase ArkType's type system capabilities for educational purposes.

Applied to files:

  • packages/arkenv/src/utils/coerce.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/utils/coerce.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} : 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-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:

  • packages/arkenv/src/utils/coerce.test.ts
  • openspec/specs/coercion/spec.md
  • apps/playgrounds/vite/vite.config.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:

  • packages/arkenv/src/utils/coerce.test.ts
📚 Learning: 2025-11-24T16:05:17.653Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T16:05:17.653Z
Learning: Use `@/openspec/AGENTS.md` to learn spec format and conventions

Applied to files:

  • openspec/specs/coercion/spec.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/**/spec.md : Use SHALL/MUST for normative requirements rather than should/may unless intentionally non-normative

Applied to files:

  • openspec/specs/coercion/spec.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 logical grouping for related environment variables in schemas

Applied to files:

  • apps/playgrounds/vite/vite.config.ts
🧬 Code graph analysis (1)
examples/with-vite-react/vite.config.ts (3)
packages/vite-plugin/src/index.ts (1)
  • arkenv (49-88)
apps/playgrounds/vite/vite.config.ts (1)
  • Env (11-16)
apps/playgrounds/vite-legacy/vite.config.ts (1)
  • Env (11-16)
⏰ 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). (2)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-e2e (e2e)
🔇 Additional comments (15)
openspec/changes/archive/2025-12-02-update-hero-videos/specs/hero-video/spec.md (3)

1-33: Scope mismatch: File appears unrelated to PR objectives.

The PR objectives describe implementing schema-directed coercion for environment variables (closing issue #228 in the arkenv package). However, this file specifies hero video display behavior for a website. While the PR includes "www" in its labels, clarify whether this hero-video spec is intentional as part of the coercion feature PR or if it was included inadvertently.


7-33: Clarify scenario format: Guideline specifies WHEN/THEN, but implementation uses GIVEN/WHEN/THEN.

The coding guideline for openspec files states scenarios should use "WHEN and THEN bullet points," but your scenarios include GIVEN as well (BDD Gherkin format). While GIVEN/WHEN/THEN is standard practice and more explicit, confirm whether the guideline intended to exclude GIVEN or if GIVEN is acceptable.


3-4: Spec content is well-structured and comprehensive.

The requirement is clearly stated with MUST (normative), and the four scenarios (Hero Video Display, Theme Switching, Responsiveness, Visual Blending) provide excellent coverage of distinct aspects. Scenarios follow proper #### Scenario: headers and use clear, testable language with theme-aware video selection, responsive scaling, and visual blending well-specified.

examples/with-vite-react/vite.config.ts (2)

11-16: Schema updates correctly leverage new coercion system.

The simplified schema definitions ("number", "boolean", "unknown") align with the centralized coercion approach. The coercion layer now handles string→primitive conversion automatically based on schema introspection, removing the need for manual parsers.

Good use of number.port built-in validator for PORT as per coding guidelines.


20-20: API signature updated to config object pattern.

The change from arkenv(Env, loadEnv(...)) to arkenv(Env, { env: loadEnv(...) }) aligns with the refactored createEnv API that accepts a config object with env and optional coerce properties.

This matches the pattern used in packages/vite-plugin/src/index.ts (line 63-65) where createEnv is called with { env: loadEnv(...) }.

apps/playgrounds/vite/vite.config.ts (2)

11-16: Schema definitions correctly simplified with coercion support.

The type declarations now leverage the new automatic coercion:

  • "unknown" accepts any value without transformation
  • "number" and "boolean" trigger automatic string→primitive coercion

This is consistent with examples/with-vite-react/vite.config.ts and eliminates manual parsing logic.


20-22: API usage and debug logging are appropriate.

The updated arkenv(Env, { env: loadEnv(...) }) call follows the new config object pattern. The console.log on line 22 is acceptable per coding guidelines since this is a playground directory—it usefully demonstrates that coercion is working by showing both the value and its runtime type.

packages/arkenv/src/utils/coerce.test.ts (8)

1-13: LGTM! Clean test setup and basic coercion test.

The imports are appropriate and the first test clearly validates the basic numeric coercion behavior with a straightforward expectation.


15-39: Excellent coverage of numeric refinements.

These tests properly validate both successful coercion and validation failures for ranges and divisors, with appropriate error message assertions to ensure user-friendly feedback.


41-53: Good documentation of case-sensitive behavior.

The comment on line 49 usefully documents the current implementation's expectation for lowercase "true"/"false", and the test validates this constraint with appropriate error checking.


55-116: Comprehensive coverage of schema variations.

Excellent test coverage across optional properties, root-level primitives, strict literals, and mixed unions. The tests validate coercion behavior for diverse schema shapes.


118-157: Strong negative test coverage.

These tests appropriately validate that invalid inputs (empty strings, whitespace, non-numeric strings, invalid boolean strings) are properly rejected with clear error messages.


159-198: Good coverage of complex scenarios.

The tests validate that coercion works correctly with nested object structures and doesn't interfere with existing ArkType morphs, ensuring compatibility with advanced schema patterns.


200-220: Excellent NaN edge case coverage.

These tests properly distinguish between number.NaN (which accepts NaN) and standard number (which rejects NaN), with a helpful comment explaining the coercion-then-validation flow.


235-246: Good validation of type mismatch errors.

This test appropriately validates that providing an array when a single value is expected results in a proper validation error after coercion.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@vercel
Copy link

vercel bot commented Dec 23, 2025

Deployment failed with the following error:

Resource is limited - try again in 6 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit

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: 1

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9a7e72 and 3a7623f.

📒 Files selected for processing (1)
  • openspec/specs/coercion/spec.md
🧰 Additional context used
📓 Path-based instructions (2)
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
**/*.{ts,tsx,json,md}

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

Use Biome for linting and formatting instead of ESLint and Prettier

Files:

  • openspec/specs/coercion/spec.md
🧠 Learnings (8)
📓 Common learnings
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
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: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use logical grouping for related environment variables in schemas
📚 Learning: 2025-11-24T16:05:17.653Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T16:05:17.653Z
Learning: Use `@/openspec/AGENTS.md` to learn spec format and conventions

Applied to files:

  • openspec/specs/coercion/spec.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/specs/coercion/spec.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/*/specs/**/spec.md : Ensure change proposals contain delta specs for each affected capability under changes/[change-id]/specs/[capability]/spec.md

Applied to files:

  • openspec/specs/coercion/spec.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: Organize specifications in openspec/specs/[capability]/spec.md with optional design.md for technical patterns

Applied to files:

  • openspec/specs/coercion/spec.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/**/spec.md : Use SHALL/MUST for normative requirements rather than should/may unless intentionally non-normative

Applied to files:

  • openspec/specs/coercion/spec.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 : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • openspec/specs/coercion/spec.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} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern

Applied to files:

  • openspec/specs/coercion/spec.md
⏰ 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). (2)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-e2e (e2e)

@vercel
Copy link

vercel bot commented Dec 23, 2025

Deployment failed with the following error:

Resource is limited - try again in 5 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit

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: 0

🧹 Nitpick comments (1)
tooling/playwright-www/package.json (1)

20-20: Use catalog: protocol for @playwright/test consistency.

The @playwright/test dependency is pinned to "1.57.0" while other devDependencies use the catalog: protocol. Update to "@playwright/test": "catalog:" to align with the monorepo's dependency management pattern.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fec2e63 and 9cef3a9.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • tooling/playwright-www/package.json
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/tests/morphs.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.test.ts
💤 Files with no reviewable changes (1)
  • tooling/playwright-www/tests/morphs.test.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.test.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:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.test.ts
tooling/playwright-www/**/*.{ts,tsx}

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

End-to-end tests should be located in tooling/playwright-www/ and test complete user workflows in real browsers with no mocking

tooling/playwright-www/**/*.{ts,tsx}: Use Playwright for end-to-end tests to validate real browser behavior across Chromium, Firefox, and WebKit
End-to-end tests should focus on user-facing behavior, not implementation details

Files:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.test.ts
**/*.{ts,tsx,json,md}

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

Use Biome for linting and formatting instead of ESLint and Prettier

Files:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/package.json
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.test.ts
tooling/*/package.json

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

Tooling in tooling/ directory contains development and testing tools that are not published to npm and excluded from changesets

Files:

  • tooling/playwright-www/package.json
**/package.json

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

Use workspace:* protocol for workspace dependencies between packages

Files:

  • tooling/playwright-www/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:

  • tooling/playwright-www/package.json
🧠 Learnings (18)
📓 Common learnings
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
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: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use logical grouping for related environment variables in schemas
📚 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 tooling/playwright-www/**/*.{ts,tsx} : Use Playwright for end-to-end tests to validate real browser behavior across Chromium, Firefox, and WebKit

Applied to files:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/package.json
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.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 tooling/playwright-www/**/*.{ts,tsx} : End-to-end tests should focus on user-facing behavior, not implementation details

Applied to files:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/package.json
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.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 tooling/playwright-www/**/*.{ts,tsx} : End-to-end tests should be located in `tooling/playwright-www/` and test complete user workflows in real browsers with no mocking

Applied to files:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/package.json
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.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:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/tests/a11y.test.ts
  • tooling/playwright-www/tests/vite-plugin-viteconfig.test.ts
📚 Learning: 2025-09-09T17:37:19.650Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 132
File: packages/arkenv/README.md:13-14
Timestamp: 2025-09-09T17:37:19.650Z
Learning: For yamcodes/arkenv project: Runtime support documentation should link to specific examples: Node.js (examples/basic), Bun (examples/with-bun), Vite (examples/with-vite-react-ts).

Applied to files:

  • tooling/playwright-www/tests/docs-navigation.test.ts
  • tooling/playwright-www/tests/a11y.test.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:

  • tooling/playwright-www/tests/docs-navigation.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} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • tooling/playwright-www/tests/docs-navigation.test.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: Applies to tooling/*/package.json : Tooling in tooling/ directory contains development and testing tools that are not published to npm and excluded from changesets

Applied to files:

  • tooling/playwright-www/package.json
📚 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 behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API

Applied to files:

  • tooling/playwright-www/tests/a11y.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} : Query by role, name, label, and text (accessibility first) in component tests

Applied to files:

  • tooling/playwright-www/tests/a11y.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} : 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:

  • tooling/playwright-www/tests/a11y.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:

  • tooling/playwright-www/tests/vite-plugin-viteconfig.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:

  • tooling/playwright-www/tests/vite-plugin-viteconfig.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} : Test edge cases including invalid and missing environment variable values

Applied to files:

  • tooling/playwright-www/tests/vite-plugin-viteconfig.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 for testing framework

Applied to files:

  • tooling/playwright-www/tests/vite-plugin-viteconfig.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:

  • tooling/playwright-www/tests/vite-plugin-viteconfig.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:

  • tooling/playwright-www/tests/vite-plugin-viteconfig.test.ts
🧬 Code graph analysis (1)
tooling/playwright-www/tests/a11y.test.ts (1)
tooling/playwright-www/tests/morphs.test.ts (10)
  • test (4-149)
  • page (30-43)
  • page (106-126)
  • page (16-28)
  • page (63-72)
  • page (5-14)
  • page (128-144)
  • page (85-94)
  • page (96-104)
  • page (54-61)
⏰ 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). (2)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-e2e (a11y)
🔇 Additional comments (3)
tooling/playwright-www/tests/vite-plugin-viteconfig.test.ts (1)

45-45: LGTM! Test assertion correctly updated for new API signature.

The test now validates the updated arkenv invocation pattern where the second argument is a config object with an env property, aligning with the API changes introduced in this PR.

tooling/playwright-www/tests/a11y.test.ts (1)

14-14: LGTM! Route updated to reflect new coercion documentation.

The accessibility test route has been correctly updated from the removed morphs page to the new coercion page, aligning with the PR's feature implementation.

tooling/playwright-www/tests/docs-navigation.test.ts (1)

10-10: LGTM! Comprehensive update from morphs to coercion.

All references to the morphs documentation page have been consistently updated to coercion across multiple test scenarios:

  • Documentation pages list (line 10)
  • Navigation flow test (lines 107-108)
  • Page title expectations (line 145)
  • Console error checking array (line 197)

The changes are thorough and align with the feature migration documented in the PR.

Also applies to: 107-108, 145-145, 197-197

@yamcodes yamcodes merged commit adaada4 into main Dec 23, 2025
19 of 20 checks passed
@yamcodes yamcodes deleted the coercion branch December 23, 2025 07:09
@arkenv-bot arkenv-bot bot mentioned this pull request Dec 23, 2025
yamcodes pushed a commit that referenced this pull request Dec 23, 2025
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## arkenv@0.8.0

### Minor Changes

- ### Coercion _[`#569`](#569)
[`adaada4`](adaada4)
[@yamcodes](https://github.com/yamcodes)_

Introduced **Schema-Directed Coercion**: now, environment variables
defined as `number` or `boolean` in your schema are automatically parsed
to their correct types.

If you want to opt-out of this feature, pass `config.coerce: false` to
`createEnv()` (`arkenv()`). Example:

    ```ts
    arkenv(schema, { coerce: false });
    ```

To learn more about the new coercion system, read [the
docs](https://arkenv.js.org/docs/arkenv/coercion).

- **BREAKING**: The `createEnv()` function signature has changed to
support a configuration object.
Instead of `createEnv(schema, env)`, use `createEnv(schema, config)`
where `config` includes `env` (`process.env` by default, like before)
and the newly added `coerce` option (`true` by default).
For example, Vite users might need to update their `vite.config.ts`:
        ```ts
const env = arkenv(Env, { env: loadEnv(mode, process.cwd(), "") });
        ```
- **BREAKING**: The custom `boolean` morph has been removed. We now use
`arktype`'s standard `boolean` instead, which is coerced when used
within `createEnv` / `arkenv`. This is only breaking if you specifically
use `boolean` unrelated to `createEnv` / `arkenv` / our plugins and
expect it to be coerced.
- **BREAKING**: `number.port` is now a strict numeric refinement
(0-65535). It no longer parses strings automatically outside of
`createEnv` / `arkenv`. This is only breaking if you specifically use
`port` unrelated to `createEnv` / `arkenv` / our plugins and expect it
to be parsed as a number.

### Patch Changes

- #### Fix error formatting
_[`#582`](#582)
[`674a2ad`](674a2ad)
[@aruaycodes](https://github.com/aruaycodes)_

The ArkEnv error message is now formatted better, using correct spacing
and removing the `f` prefix.

    Before:

        apps/playgrounds/node on  main [$] via 🤖 v24.11.1
        ❯ ns

> node-playground@ start
/Users/yamcodes/code/arkenv/apps/playgrounds/node
        > tsx --env-file .env index.ts

        /Users/yamcodes/code/arkenv/packages/arkenv/src/create-env.ts:49
                        throw new ArkEnvError(validatedEnv);
                              ^

f [ArkEnvError]: Errors found while validating environment variables
          ZED_ENV must be present (was missing)

at m
(/Users/yamcodes/code/arkenv/packages/arkenv/src/create-env.ts:49:9)
at <anonymous>
(/Users/yamcodes/code/arkenv/apps/playgrounds/node/index.ts:4:13)
at ModuleJob.run (node:internal/modules/esm/module_job:377:25)
at async onImport.tracePromise.__proto__
(node:internal/modules/esm/loader:671:26)
at async asyncRunEntryPointWithESMLoader
(node:internal/modules/run_main:101:5)

        Node.js v24.11.1
         ELIFECYCLE  Command failed with exit code 1.

    After:

apps/playgrounds/node on  improve-error-formatting [$?] via 🤖 v24.11.1
        ❯ ns

> node-playground@ start
/Users/yamcodes/code/arkenv/apps/playgrounds/node
        > tsx --env-file .env index.ts

        /Users/yamcodes/code/arkenv/packages/arkenv/src/create-env.ts:49
                        throw new ArkEnvError(validatedEnv);
                              ^

        ArkEnvError: Errors found while validating environment variables
          ZED_ENV must be present (was missing)

at m
(/Users/yamcodes/code/arkenv/packages/arkenv/src/create-env.ts:49:9)
at <anonymous>
(/Users/yamcodes/code/arkenv/apps/playgrounds/node/index.ts:4:13)
at ModuleJob.run (node:internal/modules/esm/module_job:377:25)
at async onImport.tracePromise.__proto__
(node:internal/modules/esm/loader:671:26)
at async asyncRunEntryPointWithESMLoader
(node:internal/modules/run_main:101:5)

        Node.js v24.11.1
         ELIFECYCLE  Command failed with exit code 1.

## @arkenv/bun-plugin@0.0.5

### Patch Changes

<details><summary>Updated 1 dependency</summary>

<small>


[`adaada4`](adaada4)
[`674a2ad`](674a2ad)

</small>

-   `arkenv@0.8.0`

</details>

## @arkenv/vite-plugin@0.0.22

### Patch Changes

<details><summary>Updated 1 dependency</summary>

<small>


[`adaada4`](adaada4)
[`674a2ad`](674a2ad)

</small>

-   `arkenv@0.8.0`

</details>

## @repo/keywords@0.1.0

### Minor Changes

- #### Simplify keywords for central coercion
_[`#569`](#569)
[`adaada4`](adaada4)
[@yamcodes](https://github.com/yamcodes)_

- **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 (including specific "NaN" support).

## @repo/scope@0.1.0

### Minor Changes

- #### Align scope with central coercion
_[`#569`](#569)
[`adaada4`](adaada4)
[@yamcodes](https://github.com/yamcodes)_

- **BREAKING**: Removed the custom `boolean` keyword from the root
scope. ArkEnv now uses the standard ArkType `boolean` primitive combined
with global coercion.
- Updated `number.port` to use the new strict numeric refinement, as
string parsing is now handled by global coercion.

### Patch Changes

<details><summary>Updated 1 dependency</summary>

<small>


[`adaada4`](adaada4)

</small>

-   `@repo/keywords@0.1.0`

</details>

## @repo/types@1.0.0

### Patch Changes

<details><summary>Updated 1 dependency</summary>

<small>


[`adaada4`](adaada4)

</small>

-   `@repo/scope@0.1.0`

</details>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

@arkenv/vite-plugin Issues or Pull Requests involving the Vite plugin for ArkEnv 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) github actions Pull requests that update GitHub Actions code tests This issue or PR is about adding, removing or changing tests www Improvements or additions to arkenv.js.org

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Coercion (string→number, string→boolean, etc.)

2 participants