Skip to content

Replace schema DSL with zod-based validation#19

Draft
kjanat wants to merge 4 commits into
masterfrom
claude/schema-migration-zod-vq8MK
Draft

Replace schema DSL with zod-based validation#19
kjanat wants to merge 4 commits into
masterfrom
claude/schema-migration-zod-vq8MK

Conversation

@kjanat

@kjanat kjanat commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

Removes the custom schema DSL (string-literal parser with compile-time type inference) and replaces it with zod as the single validation substrate. The schema DSL provided compile-time type parsing via template literal types and runtime AST generation, but this complexity is now consolidated into zod schemas that drive both JSON Schema generation and runtime validation.

Key Changes

  • Removed schema DSL modules:

    • src/core/schema-dsl/runtime.ts — runtime tokenizer, parser, and AST validator
    • src/core/schema-dsl/parse.ts — compile-time template literal type parser
    • src/core/schema-dsl/index.ts — public schema() function and SchemaDefinition type
    • src/core/schema-dsl/to-json-schema.ts — AST-to-JSON-Schema converter
    • src/core/schema-dsl/schema-dsl.test.ts — comprehensive DSL tests
    • src/core/schema-dsl/AGENTS.md — module documentation
  • Added zod-based schema derivation:

    • src/core/schema/zod-kinds.ts — derives canonical declared-type zod schemas from flag/arg kind descriptors; drives JSON Schema generation via z.toJSONSchema() and backs runtime validation
  • Refactored JSON Schema generation:

    • src/core/json-schema/index.ts — replaced hand-built type mappings with zod-derived schemas; added normalizeDefFragment() to normalize zod's JSON Schema output to prior DSL conventions (strip $schema/$id, collapse literal-string unions, drop redundant type on const nodes)
    • Removed flagToJsonSchemaType() / argKindToType() switch statements; now use z.toJSONSchema(flagZod(schema)) and z.toJSONSchema(argZod(schema))
  • Consolidated type guards:

    • src/core/internal/guards.ts — new module with shared isRecord() and isPlainObject() helpers (previously duplicated across config, json-schema, and resolve modules)
  • Updated validation engines:

    • src/core/resolve/coerce.ts — integrated buildZodSchema() for source-specific coercion
    • src/core/parse/index.ts — integrated buildZodSchema() for argv coercion
    • src/core/config/package-json.ts — replaced hand-checked extraction with zod schemas
  • Updated dependencies:

    • Added zod as a peer dependency (^4.0.0) in package.json

Implementation Details

  • Zod as single validation substrate: Flag/arg schemas are now derived on-demand from kind descriptors (pure functions of kind, enumValues, elementSchema) rather than stored, keeping descriptors plain and JSON-serializable.

  • JSON Schema normalization: z.toJSONSchema() output is normalized via normalizeDefFragment() to match prior DSL conventions — literal-string unions collapse from {type:'string',enum:[...]} to {enum:[...]}, boolean/string literals drop redundant type keys, and z.record() emitted propertyNames is stripped.

  • Backward compatibility: The definition meta-schema generation now uses zod's registry pattern with a custom uri callback to emit internal #/$defs/<name> cross-references, preserving the prior structure.

  • Test coverage: Removed 425-line DSL test suite; validation is now covered by zod's own test suite and integration tests in the coercion/parse engines.

kjanat added 2 commits June 7, 2026 18:04
Replace all hand-rolled validation and the homegrown schema-dsl with zod as
the single schema/validation substrate. The public builder API (flag/arg/
command) and its TypeScript inference are unchanged — only the runtime
validation engine is swapped.

- Add zod as the sole runtime dependency (drop the zero-dep policy in
  AGENTS.md/GOALS.md/README.md).
- New src/core/schema/zod-kinds.ts derives the declared-type zod schema for a
  flag/arg on demand (flagZod/argZod/buildZodSchema); not stored on the
  descriptor, so schemas stay plain, comparable, JSON-serialisable objects.
- resolve/coerce.ts and parse/index.ts now drive string/number/enum accept
  decisions through zod (safeParse); all ValidationError/ParseError messages,
  codes, details, and suggestions are preserved byte-for-byte. Custom parseFn
  still runs directly (not wrapped in zod).
- json-schema: generateInputSchema and definitionMetaSchema now built via
  z.toJSONSchema (registry + post-processor for $defs/$ref and conventions);
  output is byte-compatible with prior assertions.
- Delete src/core/schema-dsl/ entirely (tokenizer/parser/AST/validator/
  json-schema emitter); json-schema was its only consumer.
- config/package.json validation now uses zod, preserving exact failure
  semantics (return-null vs CONFIG_PARSE_ERROR wrapping).
- Consolidate duplicated isRecord/isPlainObject guards into
  src/core/internal/guards.ts.

Verified: tsgo typecheck, biome lint, dprint format, meta-descriptions:check,
2205 vitest tests, tsdown build + attw + publint all green.
Address findings from a Zod-4 best-practices review of the migration:

- packaging: move zod from `dependencies` to `peerDependencies` + a
  `devDependency`, and widen the range to `^4.0.0` (the `^3.25 || ^4` dual
  range is impossible — z.toJSONSchema/z.registry are v4-only). Consumers now
  dedupe a single zod copy; publint/attw verified.
- json-schema: stop the unconditional `anyOf`→`oneOf` rewrite in
  normalizeDefFragment (anyOf is correct for disjoint unions; oneOf was a
  latent semantic-narrowing bug). Drop z.int safe-integer bounds via the
  z.toJSONSchema `override` hook instead of matching hard-coded sentinels.
- parse: return raw directly for the string kind (argv values are already
  strings) — removes a no-op `.parse()` that was the only throwing call with
  no ParseError catch net (latent raw-ZodError leak).
- package-json: replace `z.custom(isRecord).refine(...)` bin validation with a
  native `z.record(z.string(), z.string())`.
- style: `import * as z from 'zod'` across all zod consumers.
- tests: pin the `#/$defs/<name>` cross-reference shape and the anyOf/integer
  conventions in the definition meta-schema.

Verified: typecheck, lint, format, meta-descriptions:check, 2207 tests,
tsdown build + attw + publint all green.
@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🚫 Excluded labels (none allowed) (2)
  • wip
  • cr:skip

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: c8b6a6ad-1658-4082-86bf-670f92899726

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
🚥 Pre-merge checks | ✅ 8 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Changelog Update ⚠️ Warning CHANGELOG.md was not updated despite substantial source code changes (zod migration, schema-dsl removal, package.json modifications, multiple .ts files in src/core/)—[Unreleased] section is empty. Add entries under ## [Unreleased] in CHANGELOG.md describing the zod migration, schema-dsl removal, and related changes (Added, Changed, Removed sections).
Semver Version Bump Validation ⚠️ Warning PR removes entire src/core/schema-dsl/ directory with exported symbols (Parse type, parseSchema/validateNode/nodeToJsonSchema functions) without bumping version from 2.1.0—MAJOR version bump required. Increment package.json version from 2.1.0 to 3.0.0 to reflect breaking API removals per SemVer specification.
Agents.Md Documentation Updated ⚠️ Warning Root AGENTS.md correctly updated for zod migration, but src/core/json-schema/AGENTS.md still references removed schema DSL functions and "string-literal schema DSL" that no longer exist. Update src/core/json-schema/AGENTS.md to remove DSL references and update instructions for JSON Schema generation via Zod instead of DSL parsing.
✅ Passed checks (8 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: replacing the schema DSL with zod-based validation, follows conventional commit format with an imperative verb, and is concise at 44 characters.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Release Metadata Sync ✅ Passed PR does not modify package versions, changelog headings, or release metadata; check is not applicable. All release surfaces remain aligned at v2.1.0.
Runtime Support Sync ✅ Passed PR makes no runtime support changes. None of the schema-DSL-to-zod migration files modify engines, src/runtime/support.ts, or version requirements.
No Generated Docs Artifacts ✅ Passed PR does not modify docs/.vitepress/dist/ or docs/.vitepress/cache/; git diff shows zero matches for these generated artifact directories.
Description check ✅ Passed Pull request description directly addresses the changeset: removes custom schema DSL, introduces zod-based validation, updates dependencies, and refactors validation engines.

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

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/schema-migration-zod-vq8MK

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

bun add https://pkg.pr.new/@kjanat/dreamcli@19
npm i https://pkg.pr.new/@kjanat/dreamcli@19

commit: f5748b0

@socket-security

socket-security Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedzod@​4.4.310010010093100

View full report

@kjanat kjanat self-assigned this Jun 7, 2026
@coderabbitai coderabbitai Bot added kind: feature New capability or product enhancement kind: breaking Breaking API, runtime, or packaging change area: schema Schema builders, schema DSL, and JSON Schema export area: build Build, CI, release automation, scripts, and packaging area: config Config discovery, package metadata, and loaders labels Jun 7, 2026
@kjanat kjanat added the cr:skip Skip CodeRabbit review label Jun 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
src/core/resolve/coerce.ts (1)

168-189: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep config string flags strict; this now swallows bad config.

Arrr — stringifying config number/boolean values means { region: false } quietly resolves as 'false', while src/core/json-schema/index.ts still publishes { type: 'string' } for that same field. That breaks the advertised config-schema contract and turns obvious config mistakes into silent coercions.

💡 Minimal fix
 		case 'string': {
-			const normalized =
-				source.kind === 'prompt' ||
-				(source.kind === 'config' && (typeof raw === 'number' || typeof raw === 'boolean'))
-					? String(raw)
-					: raw;
+			const normalized = source.kind === 'prompt' ? String(raw) : raw;
 			const parsed = buildZodSchema('string').safeParse(normalized);
 			if (parsed.success) return { ok: true, value: parsed.data };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/resolve/coerce.ts` around lines 168 - 189, The current string
coercion in src/core/resolve/coerce.ts (inside the case 'string' block) wrongly
stringifies config values, so change the normalization logic to only stringify
when source.kind === 'prompt' (do not stringify when source.kind === 'config');
leave buildZodSchema('string').safeParse(normalized) and the coercionError path
intact so that non-string config values produce a TYPE_MISMATCH error (use the
existing coercionError message and source.configPath for guidance).
src/core/parse/index.ts (1)

199-220: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject empty enum definitions here as well.

Arrr — these branches now trust safeParse() as the whole enum check, but buildZodSchema('enum', { enumValues: [] }) falls back to z.string(). That means a misconfigured enum with enumValues: [] will happily accept any argv value instead of failing fast. src/core/resolve/coerce.ts still keeps an explicit membership gate; the parser needs the same protection.

💡 Minimal fix
 		case 'enum': {
 			const allowed = schema.enumValues;
-			if (allowed === undefined) {
+			if (allowed === undefined || allowed.length === 0) {
 				throw new ParseError(
 					`Enum flag --${flagName} is misconfigured: no allowed values declared`,
 					{
 						code: 'INVALID_SCHEMA',
 						details: { flag: flagName, kind: 'enum', missing: 'enumValues' },
 					},
 				);
 			}
 			const result = buildZodSchema('enum', { enumValues: allowed }).safeParse(raw);
 			if (!result.success) {
 				throw new ParseError(
 					`Invalid value '${raw}' for flag ${displayName}. Allowed: ${allowed.join(', ')}`,
@@
 		case 'enum': {
 			const allowed = schema.enumValues;
-			if (allowed === undefined) {
+			if (allowed === undefined || allowed.length === 0) {
 				throw new ParseError(
 					`Enum argument <${argName}> is misconfigured: no allowed values declared`,
 					{
 						code: 'INVALID_SCHEMA',
 						details: { arg: argName, kind: 'enum', missing: 'enumValues' },
 					},
 				);
 			}
 			const result = buildZodSchema('enum', { enumValues: allowed }).safeParse(raw);

Also applies to: 276-297

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/parse/index.ts` around lines 199 - 220, The enum branch in
parse/index.ts currently trusts buildZodSchema('enum', { enumValues }) and
safeParse, which allows a misconfigured empty enum (enumValues = []) to fall
back to z.string() and accept any input; add an explicit check after grabbing
const allowed = schema.enumValues to reject empty arrays (allowed.length === 0)
by throwing a ParseError (same shape as the missing-case error, code
'INVALID_SCHEMA' with details including flag: flagName, kind: 'enum', missing:
'enumValues') so empty enum definitions fail fast; apply the identical check to
the other enum handling block referenced around lines 276-297.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/completion/shells/shared.ts`:
- Around line 14-15: The file imports createSchema, CommandSchema, and
FlagSchema from the barrel '`#internals/core/schema/index.ts`'; replace those
barrel imports with direct imports from the modules that define them so the
runtime import for createSchema is no longer through the barrel and the types
CommandSchema and FlagSchema are imported from their specific type-definition
modules; update the import statements in shared.ts accordingly to pull
createSchema from its implementation module and the two types from their exact
declaration modules to avoid barrel-induced cycles.

---

Outside diff comments:
In `@src/core/parse/index.ts`:
- Around line 199-220: The enum branch in parse/index.ts currently trusts
buildZodSchema('enum', { enumValues }) and safeParse, which allows a
misconfigured empty enum (enumValues = []) to fall back to z.string() and accept
any input; add an explicit check after grabbing const allowed =
schema.enumValues to reject empty arrays (allowed.length === 0) by throwing a
ParseError (same shape as the missing-case error, code 'INVALID_SCHEMA' with
details including flag: flagName, kind: 'enum', missing: 'enumValues') so empty
enum definitions fail fast; apply the identical check to the other enum handling
block referenced around lines 276-297.

In `@src/core/resolve/coerce.ts`:
- Around line 168-189: The current string coercion in src/core/resolve/coerce.ts
(inside the case 'string' block) wrongly stringifies config values, so change
the normalization logic to only stringify when source.kind === 'prompt' (do not
stringify when source.kind === 'config'); leave
buildZodSchema('string').safeParse(normalized) and the coercionError path intact
so that non-string config values produce a TYPE_MISMATCH error (use the existing
coercionError message and source.configPath for guidance).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 35109c21-ee44-4aca-975c-c1ce82020146

📥 Commits

Reviewing files that changed from the base of the PR and between 763e386 and a6b7f5e.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • AGENTS.md
  • GOALS.md
  • README.md
  • package.json
  • src/core/completion/shells/shared.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/internal/guards.ts
  • src/core/json-schema/index.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/resolve/errors.ts
  • src/core/schema-dsl/AGENTS.md
  • src/core/schema-dsl/index.ts
  • src/core/schema-dsl/parse.ts
  • src/core/schema-dsl/runtime.ts
  • src/core/schema-dsl/schema-dsl.test.ts
  • src/core/schema-dsl/to-json-schema.ts
  • src/core/schema/zod-kinds.ts
💤 Files with no reviewable changes (6)
  • src/core/schema-dsl/index.ts
  • src/core/schema-dsl/AGENTS.md
  • src/core/schema-dsl/schema-dsl.test.ts
  • src/core/schema-dsl/to-json-schema.ts
  • src/core/schema-dsl/runtime.ts
  • src/core/schema-dsl/parse.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use tabs for indentation, single quotes for strings, semicolons at end of statements, and LF for line endings

Use import type for type-only imports in TypeScript

Include .ts extensions in all relative imports

Use strict TypeScript everywhere with exactOptionalPropertyTypes enabled; use conditional spreads for optional properties

Use explicit named re-exports only; do not use export *

Files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Include @module JSDoc at the top of source files; mark non-public API with @internal

Files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Public API should be factory-first: use cli(), command(), flag.*(), createOutput(), createAdapter() naming patterns

Do not use process.* or runtime-specific APIs in src/core/; abstract runtime I/O through RuntimeAdapter, WriteFn, or ReadFn

Files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
**

⚙️ CodeRabbit configuration file

**: # PROJECT KNOWLEDGE BASE

Generated: 2026-04-07 Commit: 1479d26 Branch: master

OVERVIEW

Schema-first, fully typed TypeScript CLI framework. Zero runtime deps. In-repo exports point at
src/*.ts; published Node defaults point at dist/*.mjs, while Bun and Deno keep source exports.

Read @DISCOVERIES.md before planning, editing, or running task workflows.

STRUCTURE

src/
├── index.ts                # public package surface
├── runtime.ts              # `./runtime` subpath barrel
├── testkit.ts              # `./testkit` subpath barrel
├── core/
│   ├── cli/                # top-level CLI orchestration, plugins, root surface
│   ├── schema/             # builder DSL, type inference, middleware surface
│   ├── resolve/            # argv/env/config/prompt/default precedence
│   ├── output/             # stdout/stderr/json/table/activity dispatch
│   ├── completion/         # shell completion generators
│   ├── json-schema/        # definition schema + input schema generation
│   ├── parse/              # tokenizer + schema-aware raw parse
│   ├── prompt/             # terminal/test prompt engines
│   ├── config/             # config discovery + package.json walk-up
│   ├── help/               # schema-driven help formatter
│   └── testkit/            # in-process test harness
└── runtime/                # Node/Bun/Deno adapters + detection

docs/
├── .vitepress/             # config, data loaders, theme, custom Vite plugins
├── concepts/               # hand-written docs
├── guide/                  # hand-written docs
├── examples/               # generated routes backed by `../examples/*.ts`
└── reference/              # overview pages + dynamic symbol routes

scripts/                    # build, release, and project automation
examples/                   # runnable examples + `examples/gh` workspace canary
specs/                      # planning/design docs

WHERE TO LOOK

| Task | Lo...

Files:

  • src/core/internal/guards.ts
  • README.md
  • AGENTS.md
  • GOALS.md
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • package.json
  • src/core/json-schema/index.ts
src/core/json-schema/**/*.ts

📄 CodeRabbit inference engine (src/core/json-schema/AGENTS.md)

Use @internal JSDoc tags to mark internal APIs; docs and meta-description tooling filter on them

Files:

  • src/core/json-schema/json-schema.test.ts
  • src/core/json-schema/index.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Co-locate tests as *.test.ts files; use describe() + it(), em dash in suite titles, // === and // --- section markers

Do not use lifecycle hooks, snapshots, or module mocks in tests

Output assertions in tests must include trailing newline character

Files:

  • src/core/json-schema/json-schema.test.ts
src/core/json-schema/**

⚙️ CodeRabbit configuration file

src/core/json-schema/**: # json-schema — Definition metadata + input schema generation

OVERVIEW

Single large module plus one generated companion file. It emits both DreamCLI definition metadata
and draft-2020-12 input schemas, and it bridges the string-literal schema DSL into JSON Schema
output.

FILES

File Purpose
index.ts generateSchema(), generateInputSchema(), serialization helpers
meta-descriptions.generated.ts generated descriptions injected into the definition meta-schema
json-schema.test.ts behavior contract for both outputs

WHERE TO LOOK

Task Location Notes
Change definition schema shape generateSchema() CLI tree, flags, args, examples, hidden and prompt filtering
Change input validation schema generateInputSchema() JSON Schema 2020-12 for config/editor use cases
Change DSL -> JSON Schema bridge parseSchema(), nodeToJsonSchema() in index.ts feeds custom and DSL flag shapes
Regenerate descriptions meta-descriptions.generated.ts, ../../../scripts/build-meta-descriptions.ts script is source of truth

CONVENTIONS

  • Output must stay JSON-ser...

Files:

  • src/core/json-schema/json-schema.test.ts
  • src/core/json-schema/index.ts
src/core/{cli,completion,output,prompt,resolve}/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not import through barrels in cli/, completion/, output/, prompt/, resolve/, and runtime/; use direct-file imports to avoid cycles

Files:

  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/resolve/coerce.ts
src/core/resolve/**

⚙️ CodeRabbit configuration file

src/core/resolve/**: # resolve — Flag/arg value resolution chain

Multi-file module (split from monolithic index). 8 source files, ~1333 source lines.

RESOLUTION ORDER

CLI argv -> environment variable -> config file -> interactive prompt -> default value

Each source tried in order; first non-undefined wins. Missing required values with no source trigger
ValidationError.

FILES

File Lines Purpose
index.ts 108 Barrel — re-exports public API
flags.ts 201 resolveFlags() — all flags: CLI -> env -> config -> prompt -> default
args.ts 141 resolveArgs() — parsed -> default -> required validation
coerce.ts 429 coerceValue() — unified raw value -> flag's declared kind
config.ts 25 resolveConfigPath() — dotted path lookup in config object
errors.ts 228 Error aggregation + throwAggregatedErrors()
property.ts 87 Property path resolution utilities
contracts.ts 114 ResolveOptions, CoerceResult, CoerceSource types

KEY FUNCTIONS

Function File Role
resolve() index.ts Main entry — orchestrates full resolution for a command
resolveFlags() flags.ts All flags: CLI -> env -> config -> prompt -> default
resolveArgs() args.ts All args: parsed -> default -> required val...

Files:

  • src/core/resolve/errors.ts
  • src/core/resolve/coerce.ts
src/core/completion/shells/*.ts

📄 CodeRabbit inference engine (src/core/completion/AGENTS.md)

Organize shell completion generators in per-shell modules under shells/ directory, with each shell having its own dedicated generator file (bash.ts, zsh.ts, fish.ts, powershell.ts)

Files:

  • src/core/completion/shells/shared.ts
src/core/completion/shells/shared.ts

📄 CodeRabbit inference engine (src/core/completion/AGENTS.md)

src/core/completion/shells/shared.ts: Implement shared command tree infrastructure (CommandNode, walkCommandTree(), escaping utilities, versionTag) in shells/shared.ts
Import collectPropagatedFlags() directly from cli/propagate.ts (@internal file) in shells/shared.ts to handle flag inheritance in nested commands

Files:

  • src/core/completion/shells/shared.ts
src/core/completion/**

⚙️ CodeRabbit configuration file

src/core/completion/**: # completion — Shell completion script generation

Split into per-shell generators under shells/. Barrel index.ts re-exports public API and
dispatches via generateCompletion().

FILES

File Lines Purpose
index.ts 88 Barrel — Shell type, SHELLS constant, dispatch
shells/shared.ts 160 CommandNode, walkCommandTree, escaping, versionTag
shells/bash.ts 275 generateBashCompletion() + all bash helpers
shells/zsh.ts 280 generateZshCompletion() + all zsh helpers
shells/fish.ts 256 generateFishCompletion() + fish path scanner helpers
shells/powershell.ts 438 generatePowerShellCompletion() + metadata helpers

PUBLIC API

Symbol Exported from Role
generateCompletion() index.ts Shell-agnostic dispatch -> per-shell generators
generateBashCompletion() index.ts Bash completion script from command tree
generateZshCompletion() index.ts Zsh completion script from command tree
generateFishCompletion() index.ts Fish completion script from command tree
generatePowerShellCompletion() index.ts PowerShell completion script from command tree
SHELLS index.ts readonly ['bash', 'zsh', 'fish', 'powershell']
CompletionOptions index.ts Options type (re-exported from shared.ts)
Shell index.ts Union type of supported...

Files:

  • src/core/completion/shells/shared.ts
src/core/schema/**

⚙️ CodeRabbit configuration file

src/core/schema/**: # schema — Command/Flag/Arg/Middleware builders + prompt config types

Multi-file module in core/. All others (except resolve, output, completion) use single index.ts.

FILES

File Lines Purpose
command.ts 1466 CommandBuilder<F, A, C> — fluent builder + Out interface + schema
flag.ts 753 FlagBuilderflag.string(), .boolean(), .number(), .count(), .enum(), .custom()
arg.ts 713 ArgBuilderarg.string(), .number(), .enum()
activity.ts 150 Activity types — SpinnerHandle, ProgressHandle, ActivityEvent, etc.
middleware.ts 164 middleware<Output>(handler) factory — phantom-branded Middleware<Output>
prompt.ts 70 Prompt config types — PromptConfig discriminated union (4 kinds)
run.ts 47 RunResult — structured execution result (re-exported by testkit)
index.ts 80 Barrel — re-exports all public symbols

TYPE SYSTEM PATTERNS

  • F accumulator: {} & Record<name, InferFlag<...>> grows per .flag() call
  • A accumulator: same pattern for .arg()
  • C accumulator: Record<string, never> replaced entirely on first .middleware(), then
    intersection-grown via WidenContext<C, Output>
  • {} as identity element: biome-ignore noBannedTypes on CommandBuilder class generic
    defaults — justified, do not "fix"
  • Phantom brand: Middleware<Output> carries type info at compile time, erased at runtime.
    Same for ...

Files:

  • src/core/schema/zod-kinds.ts
src/core/config/**

⚙️ CodeRabbit configuration file

src/core/config/**: # config — Config discovery + package.json metadata walk-up

OVERVIEW

Config loading is adapter-driven and side-effect free from the module's perspective. It covers both
user config discovery and packageJson() metadata inference.

FILES

File Purpose
index.ts config search paths, loaders, parsing, discovery
package-json.ts nearest package.json walk-up + CLI name inference
config.test.ts discovery and load behavior
package-json.test.ts metadata inference

WHERE TO LOOK

Task Location Notes
Change default config locations buildConfigSearchPaths() cwd dotfile, cwd explicit config, platform config dir
Change custom format loading FormatLoader, buildLoaderMap() JSON built in; later loaders override earlier ones
Change main discovery flow discoverConfig() first found path wins, parses through adapter
Change CLI metadata inference discoverPackageJson(), inferCliName() backs CLIBuilder.packageJson()

CONVENTIONS

  • All I/O flows through a narrow RuntimeAdapter surface; keep it testable with virtual filesystems
  • Config roots must be plain objects even if a loader can parse other JSON or YAML values
  • JSON is always built in and ordered first in search-path and loader resolution
  • package-json.ts is a convenience feature: malformed or missing package metadata returns null,
    not a hard failure
    ...

Files:

  • src/core/config/index.ts
  • src/core/config/package-json.ts
src/core/parse/**

⚙️ CodeRabbit configuration file

src/core/parse/**: # parse — Tokenizer + schema-aware raw parser

OVERVIEW

Single-file parser module. It tokenizes raw argv without schema knowledge, then parses against
CommandSchema into raw values for the resolve layer.

FILES

File Purpose
index.ts tokenize(), parse(), flag/arg coercion, lookup helpers
parse.test.ts parser contract, edge cases, regressions

WHERE TO LOOK

Task Location Notes
Change raw argv splitting tokenize() --, --flag=value, grouped short flags, lone -
Change alias or canonical lookup buildFlagLookup() names and aliases normalize to canonical keys
Change parse-time coercion coerceFlagValue(), coerceArgValue() parse-time only, before resolve and defaults
Change main parse flow parse() consumes tokens into raw flags and args or throws ParseError

CONVENTIONS

  • Keep tokenizer schema-agnostic; resolve/default/env/config behavior belongs elsewhere
  • Single - is a positional stdin sentinel, not a flag
  • Boolean explicit values accept only true/false and 1/0
  • Parse errors use ParseError with structured codes and details, not ad hoc strings

ANTI-PATTERNS

  • Do not read env, config, prompts, or defaults here; that is resolve/
  • Do not bypass canonical alias mapping when storing parsed flags
  • Do not blur tokenization and parsing responsibilities to simplify a small chang...

Files:

  • src/core/parse/index.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-07T21:58:58.006Z
Learning: Do not edit `docs/.vitepress/dist/` or `docs/.vitepress/cache/`; these are generated artifacts
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-07T21:58:58.006Z
Learning: Do not treat `docs/.vitepress/data/` as docs-only; scripts import it for generated source and docs artifacts
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-07T21:58:58.006Z
Learning: Do not replace `bun run gh-project:*` with ad hoc GitHub project mutations; use the provided workflow helpers
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-07T21:58:58.006Z
Learning: Keep dependencies minimal; `zod` is the only peer dependency — justify any further additions
📚 Learning: 2026-02-11T11:57:27.623Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 3
File: src/core/cli/cli-completion-e2e.test.ts:9-16
Timestamp: 2026-02-11T11:57:27.623Z
Learning: Enforce explicit .ts extensions in all relative imports for TypeScript source files (enabled by allowImportingTsExtensions and noEmit in tsconfig.json). This applies to both static and dynamic imports. For each TypeScript file, update relative import paths to end with .ts (e.g., './utils/helper' -> './utils/helper.ts'). Ensure tooling (linting/eslint rules or a codemod) flags missing extensions and provides a quick fix. This guideline should cover all TypeScript files in the repo, not just a single test or module.

Applied to files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
📚 Learning: 2026-04-06T11:25:57.444Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/spinner-progress.ts:2-12
Timestamp: 2026-04-06T11:25:57.444Z
Learning: In this repo, enforce that TypeScript source files under `src/` include the required `module` JSDoc tag (where the project’s lint/review rules expect it). Do not flag missing `module` tags in files under `examples/`, since those are documentation/example scripts (e.g., `examples/*.ts`).

Applied to files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
📚 Learning: 2026-04-06T11:26:11.173Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/json-mode.ts:2-15
Timestamp: 2026-04-06T11:26:11.173Z
Learning: In this repository, `module` JSDoc tags are required for TypeScript source files under `src/` (e.g., `src/**/*.ts`). Runnable demo/example scripts under `examples/` are not part of this requirement and should not be flagged for missing `module`.

Applied to files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
📚 Learning: 2026-04-06T11:28:55.224Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/.vitepress/theme/index.ts:1-16
Timestamp: 2026-04-06T11:28:55.224Z
Learning: In the kjanat/dreamcli repo, enforce the `module` JSDoc tag requirement only for TypeScript source files under `src/` (i.e., `src/**/*.ts`). Do not require `module` for files under `docs/`, including anything in `docs/.vitepress/**`, since those are part of the VitePress docs pipeline.

Applied to files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
📚 Learning: 2026-04-06T11:26:04.030Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/middleware.ts:2-11
Timestamp: 2026-04-06T11:26:04.030Z
Learning: In the kjanat/dreamcli repository, require the `module` JSDoc tag only for library source files under `src/` (e.g., `src/**/*.ts`). Files outside `src/` such as runnable demo/example scripts under `examples/` are not considered source code for this rule and should not be required to include `module`.

Applied to files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
📚 Learning: 2026-04-06T18:24:44.371Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/reference/api.md:8-8
Timestamp: 2026-04-06T18:24:44.371Z
Learning: In the kjanat/dreamcli repo, the explicit type annotation `Readonly<Record<string, string>>` applied to `const` object literals is an intentional documentation/intent pattern. Do not flag it as redundant or unnecessary (e.g., for being inferable) when reviewing TypeScript/TSX files; treat this explicitness as acceptable by design.

Applied to files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
📚 Learning: 2026-04-06T18:40:01.263Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/.vitepress/vite-plugins/source-artifacts.ts:62-83
Timestamp: 2026-04-06T18:40:01.263Z
Learning: For this repository, Windows is explicitly not a supported/targeted platform. During code review, do not raise issues about Windows-specific path separators or normalization differences (e.g., use of `path.sep`, handling forward-slash vs backslash, or `normalize()`-related concerns). These checks should be treated as out-of-scope because the project is intended for Linux/macOS only.

Applied to files:

  • src/core/internal/guards.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/json-schema/index.ts
📚 Learning: 2026-02-10T16:25:08.867Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 1
File: AGENTS.md:12-12
Timestamp: 2026-02-10T16:25:08.867Z
Learning: In repository kjanat/dreamcli, prefer using the filename syntax (e.g., GOALS.md) when referencing files in Markdown documentation, and treat references that do not follow this style as non-issues. This pattern applies to all Markdown files across the project.

Applied to files:

  • README.md
  • AGENTS.md
  • GOALS.md
📚 Learning: 2026-02-12T15:52:24.166Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 4
File: src/core/resolve/resolve-arg-env.test.ts:1-7
Timestamp: 2026-02-12T15:52:24.166Z
Learning: In test files, do not require the module JSDoc tag at the top. This rule applies to all test files, while non-test source files should still require the module tag. Use the pattern **/*.test.{ts,tsx} to cover all test TypeScript test files (adjust if your project uses only .ts tests).

Applied to files:

  • src/core/json-schema/json-schema.test.ts
📚 Learning: 2026-04-02T00:14:17.279Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 7
File: src/core/cli/cli.test.ts:14-14
Timestamp: 2026-04-02T00:14:17.279Z
Learning: In kjanat/dreamcli test files (src/**/*.test.ts), do not flag differences in section separator style between `// ---` and `// ===`. This style is intentionally used by the author for all section levels (including top-level sections) in tests, so separator casing/choice should not be treated as a guideline violation in code review.

Applied to files:

  • src/core/json-schema/json-schema.test.ts
📚 Learning: 2026-04-06T21:55:25.291Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: src/core/cli/cli-completion-contract.test.ts:167-194
Timestamp: 2026-04-06T21:55:25.291Z
Learning: In kjanat/dreamcli’s bash completion implementation, the generator (`src/core/completion/shells/bash.ts`) intentionally emits per-node `compgen -W ...` blocks inside `case "$subcmd_path" in ... esac` with `return ;;` after each branch, and then unconditionally emits the root-level `compgen -W` block immediately after the `esac`. Therefore, the root `compgen -W` is always the LAST `compgen -W` in the script; the test helper (`src/core/completion/completion-test-helpers.ts`), which extracts root words via `matches[matches.length - 1]`, is correct. During code review, do NOT flag this as a bug if root word extraction relies on the final `compgen -W` ordering.

Applied to files:

  • src/core/completion/shells/shared.ts
📚 Learning: 2026-04-07T08:45:53.051Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: package.json:121-129
Timestamp: 2026-04-07T08:45:53.051Z
Learning: When reviewing package.json `devEngines`, do not treat EBADDEVENGINES warnings as a breaking issue if the block intentionally uses Bun (e.g., `{ "name": "bun" }`) and the corresponding `onFail` values are soft (`onFail: "warn"` or `onFail: "ignore"`). npm may consider `bun` an invalid/unsupported engine name and warn, but with these `onFail` settings it won’t hard-fail—so the intent should be respected unless `onFail` is set to `fail` or similar hard-failure behavior.

Applied to files:

  • package.json
🪛 OpenGrep (1.22.0)
src/core/json-schema/index.ts

[WARNING] 908-908: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 909-909: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 919-919: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 920-920: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 925-925: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 935-935: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)

🔇 Additional comments (8)
AGENTS.md (1)

7-9: LGTM!

Also applies to: 83-83

GOALS.md (1)

353-354: LGTM!

README.md (1)

6-6: LGTM!

package.json (1)

131-135: LGTM!

src/core/internal/guards.ts (1)

1-37: LGTM!

src/core/config/index.ts (1)

14-30: LGTM!

Also applies to: 337-341

src/core/config/package-json.ts (1)

11-49: LGTM!

Also applies to: 173-183

src/core/resolve/errors.ts (1)

13-13: LGTM!

Comment thread src/core/completion/shells/shared.ts Outdated
- completion/shells/shared.ts: import createSchema/CommandSchema/FlagSchema
  from their defining modules instead of the schema barrel (barrel imports are
  banned in completion/ to avoid cycles).
- parse/index.ts: reject empty enumValues in both enum branches — an empty
  array made buildZodSchema fall back to z.string() and accept anything;
  now fails fast as INVALID_SCHEMA, matching the resolve coercion engine.
- json-schema/AGENTS.md: drop stale schema-DSL references (parseSchema/
  nodeToJsonSchema); document the zod -> JSON Schema bridge instead.
- CHANGELOG.md: fill the [Unreleased] section (Added/Changed/Removed) for the
  zod migration and schema-dsl removal.

Verified: typecheck, lint, format, 2207 tests green.
kjanat added a commit that referenced this pull request Jun 7, 2026
- completion/shells/shared.ts: import createSchema/CommandSchema/FlagSchema
  from their defining modules instead of the schema barrel (barrel imports are
  banned in completion/ to avoid cycles).
- parse/index.ts: reject empty enumValues in both enum branches — an empty
  array made buildZodSchema fall back to z.string() and accept anything;
  now fails fast as INVALID_SCHEMA, matching the resolve coercion engine.
- json-schema/AGENTS.md: drop stale schema-DSL references (parseSchema/
  nodeToJsonSchema); document the zod -> JSON Schema bridge instead.
- CHANGELOG.md: fill the [Unreleased] section (Added/Changed/Removed) for the
  zod migration and schema-dsl removal.

Verified: typecheck, lint, format, 2207 tests green.

https://claude.ai/code/session_01X9azTxT5F23C48JvTCxDCx
Signed-off-by: Kaj Kowalski <info@kajkowalski.nl>
@kjanat kjanat force-pushed the claude/schema-migration-zod-vq8MK branch from dd20fa5 to f5748b0 Compare June 9, 2026 09:49
@kjanat kjanat removed the cr:skip Skip CodeRabbit review label Jun 9, 2026
@coderabbitai coderabbitai Bot added area: resolve Argv, env, config, prompt, and default resolution and removed kind: feature New capability or product enhancement kind: breaking Breaking API, runtime, or packaging change area: schema Schema builders, schema DSL, and JSON Schema export area: build Build, CI, release automation, scripts, and packaging area: config Config discovery, package metadata, and loaders labels Jun 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 39-50: Rewrite the changelog block for clarity: change
"pre-loaded" to "preloaded", tighten punctuation so the clause "...skipping
filesystem discovery entirely." flows without the extra comma around "so" in the
next sentence, and rephrase the "{ from }" example to a clearer form (avoid
using "from:" with a trailing colon — show it as the option name `{ from }` or
"pass { from: import.meta.url }") while keeping references to
CLIBuilder.packageJson(), .packageJson(data), .packageJson({ from }) and
discoverPackageJson(adapter, startDir?) intact; ensure explicit
`.version()`/`.description()` still "win" wording remains but tidy the sentence
to read smoothly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9907719c-8d4e-4294-bf6e-b8b2080826db

📥 Commits

Reviewing files that changed from the base of the PR and between a6b7f5e and f5748b0.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (22)
  • AGENTS.md
  • CHANGELOG.md
  • GOALS.md
  • README.md
  • package.json
  • src/core/completion/shells/shared.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/internal/guards.ts
  • src/core/json-schema/AGENTS.md
  • src/core/json-schema/index.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/resolve/errors.ts
  • src/core/schema-dsl/AGENTS.md
  • src/core/schema-dsl/index.ts
  • src/core/schema-dsl/parse.ts
  • src/core/schema-dsl/runtime.ts
  • src/core/schema-dsl/schema-dsl.test.ts
  • src/core/schema-dsl/to-json-schema.ts
  • src/core/schema/zod-kinds.ts
💤 Files with no reviewable changes (6)
  • src/core/schema-dsl/AGENTS.md
  • src/core/schema-dsl/to-json-schema.ts
  • src/core/schema-dsl/parse.ts
  • src/core/schema-dsl/runtime.ts
  • src/core/schema-dsl/index.ts
  • src/core/schema-dsl/schema-dsl.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (17)
**

⚙️ CodeRabbit configuration file

**: # PROJECT KNOWLEDGE BASE

Generated: 2026-04-07 Commit: 1479d26 Branch: master

OVERVIEW

Schema-first, fully typed TypeScript CLI framework. Zero runtime deps. In-repo exports point at
src/*.ts; published Node defaults point at dist/*.mjs, while Bun and Deno keep source exports.

Read @DISCOVERIES.md before planning, editing, or running task workflows.

STRUCTURE

src/
├── index.ts                # public package surface
├── runtime.ts              # `./runtime` subpath barrel
├── testkit.ts              # `./testkit` subpath barrel
├── core/
│   ├── cli/                # top-level CLI orchestration, plugins, root surface
│   ├── schema/             # builder DSL, type inference, middleware surface
│   ├── resolve/            # argv/env/config/prompt/default precedence
│   ├── output/             # stdout/stderr/json/table/activity dispatch
│   ├── completion/         # shell completion generators
│   ├── json-schema/        # definition schema + input schema generation
│   ├── parse/              # tokenizer + schema-aware raw parse
│   ├── prompt/             # terminal/test prompt engines
│   ├── config/             # config discovery + package.json walk-up
│   ├── help/               # schema-driven help formatter
│   └── testkit/            # in-process test harness
└── runtime/                # Node/Bun/Deno adapters + detection

docs/
├── .vitepress/             # config, data loaders, theme, custom Vite plugins
├── concepts/               # hand-written docs
├── guide/                  # hand-written docs
├── examples/               # generated routes backed by `../examples/*.ts`
└── reference/              # overview pages + dynamic symbol routes

scripts/                    # build, release, and project automation
examples/                   # runnable examples + `examples/gh` workspace canary
specs/                      # planning/design docs

WHERE TO LOOK

| Task | Lo...

Files:

  • README.md
  • GOALS.md
  • package.json
  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • CHANGELOG.md
  • src/core/config/index.ts
  • src/core/json-schema/AGENTS.md
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • AGENTS.md
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use tabs for indentation, single quotes, semicolons, and LF line endings

Use import type for type-only imports in TypeScript

Include .ts extensions in all relative imports

Enable strict TypeScript everywhere; use exactOptionalPropertyTypes to enforce conditional spreads

Use explicit named re-exports only; do not use export * for barrels

Add @module JSDoc at the top of source files and mark non-public API with @internal

Keep public API factory-first with function names: cli(), command(), flag.*(), createOutput(), createAdapter()

Minimize dependencies — zod (peer dependency) is the only one; justify any further additions

Files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep core runtime-agnostic; do not use process.* or runtime-specific APIs; route host I/O through RuntimeAdapter, WriteFn, or ReadFn

Files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
src/core/{cli,completion,output,prompt,resolve,runtime}/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not import through barrels when it would create cycles; use direct-file imports intentionally

Files:

  • src/core/resolve/errors.ts
  • src/core/completion/shells/shared.ts
  • src/core/resolve/coerce.ts
src/core/resolve/**

⚙️ CodeRabbit configuration file

src/core/resolve/**: # resolve — Flag/arg value resolution chain

Multi-file module (split from monolithic index). 8 source files, ~1333 source lines.

RESOLUTION ORDER

CLI argv -> environment variable -> config file -> interactive prompt -> default value

Each source tried in order; first non-undefined wins. Missing required values with no source trigger
ValidationError.

FILES

File Lines Purpose
index.ts 108 Barrel — re-exports public API
flags.ts 201 resolveFlags() — all flags: CLI -> env -> config -> prompt -> default
args.ts 141 resolveArgs() — parsed -> default -> required validation
coerce.ts 429 coerceValue() — unified raw value -> flag's declared kind
config.ts 25 resolveConfigPath() — dotted path lookup in config object
errors.ts 228 Error aggregation + throwAggregatedErrors()
property.ts 87 Property path resolution utilities
contracts.ts 114 ResolveOptions, CoerceResult, CoerceSource types

KEY FUNCTIONS

Function File Role
resolve() index.ts Main entry — orchestrates full resolution for a command
resolveFlags() flags.ts All flags: CLI -> env -> config -> prompt -> default
resolveArgs() args.ts All args: parsed -> default -> required val...

Files:

  • src/core/resolve/errors.ts
  • src/core/resolve/coerce.ts
CHANGELOG.md

📄 CodeRabbit inference engine (Custom checks)

If a version bump is detected in CHANGELOG.md, the new section header MUST match the exact new version number in the format: '## [X.Y.Z] - YYYY-MM-DD'. If NO version bump is detected, changes MUST be added under the existing '## [Unreleased]' section with descriptive entries (e.g., Added, Changed, Fixed, Removed).

Files:

  • CHANGELOG.md
src/core/config/**

⚙️ CodeRabbit configuration file

src/core/config/**: # config — Config discovery + package.json metadata walk-up

OVERVIEW

Config loading is adapter-driven and side-effect free from the module's perspective. It covers both
user config discovery and packageJson() metadata inference.

FILES

File Purpose
index.ts config search paths, loaders, parsing, discovery
package-json.ts nearest package.json walk-up + CLI name inference
config.test.ts discovery and load behavior
package-json.test.ts metadata inference

WHERE TO LOOK

Task Location Notes
Change default config locations buildConfigSearchPaths() cwd dotfile, cwd explicit config, platform config dir
Change custom format loading FormatLoader, buildLoaderMap() JSON built in; later loaders override earlier ones
Change main discovery flow discoverConfig() first found path wins, parses through adapter
Change CLI metadata inference discoverPackageJson(), inferCliName() backs CLIBuilder.packageJson()

CONVENTIONS

  • All I/O flows through a narrow RuntimeAdapter surface; keep it testable with virtual filesystems
  • Config roots must be plain objects even if a loader can parse other JSON or YAML values
  • JSON is always built in and ordered first in search-path and loader resolution
  • package-json.ts is a convenience feature: malformed or missing package metadata returns null,
    not a hard failure
    ...

Files:

  • src/core/config/index.ts
  • src/core/config/package-json.ts
src/core/json-schema/**

⚙️ CodeRabbit configuration file

src/core/json-schema/**: # json-schema — Definition metadata + input schema generation

OVERVIEW

Single large module plus one generated companion file. It emits both DreamCLI definition metadata
and draft-2020-12 input schemas, and it bridges the string-literal schema DSL into JSON Schema
output.

FILES

File Purpose
index.ts generateSchema(), generateInputSchema(), serialization helpers
meta-descriptions.generated.ts generated descriptions injected into the definition meta-schema
json-schema.test.ts behavior contract for both outputs

WHERE TO LOOK

Task Location Notes
Change definition schema shape generateSchema() CLI tree, flags, args, examples, hidden and prompt filtering
Change input validation schema generateInputSchema() JSON Schema 2020-12 for config/editor use cases
Change DSL -> JSON Schema bridge parseSchema(), nodeToJsonSchema() in index.ts feeds custom and DSL flag shapes
Regenerate descriptions meta-descriptions.generated.ts, ../../../scripts/build-meta-descriptions.ts script is source of truth

CONVENTIONS

  • Output must stay JSON-ser...

Files:

  • src/core/json-schema/AGENTS.md
  • src/core/json-schema/index.ts
  • src/core/json-schema/json-schema.test.ts
src/core/completion/shells/*.ts

📄 CodeRabbit inference engine (src/core/completion/AGENTS.md)

Organize shell completion generators in per-shell modules under shells/ directory, with each shell having its own dedicated generator file (bash.ts, zsh.ts, fish.ts, powershell.ts)

Files:

  • src/core/completion/shells/shared.ts
src/core/completion/shells/shared.ts

📄 CodeRabbit inference engine (src/core/completion/AGENTS.md)

src/core/completion/shells/shared.ts: Implement shared command tree infrastructure (CommandNode, walkCommandTree(), escaping utilities, versionTag) in shells/shared.ts
Import collectPropagatedFlags() directly from cli/propagate.ts (@internal file) in shells/shared.ts to handle flag inheritance in nested commands

Files:

  • src/core/completion/shells/shared.ts
src/core/completion/**

⚙️ CodeRabbit configuration file

src/core/completion/**: # completion — Shell completion script generation

Split into per-shell generators under shells/. Barrel index.ts re-exports public API and
dispatches via generateCompletion().

FILES

File Lines Purpose
index.ts 88 Barrel — Shell type, SHELLS constant, dispatch
shells/shared.ts 160 CommandNode, walkCommandTree, escaping, versionTag
shells/bash.ts 275 generateBashCompletion() + all bash helpers
shells/zsh.ts 280 generateZshCompletion() + all zsh helpers
shells/fish.ts 256 generateFishCompletion() + fish path scanner helpers
shells/powershell.ts 438 generatePowerShellCompletion() + metadata helpers

PUBLIC API

Symbol Exported from Role
generateCompletion() index.ts Shell-agnostic dispatch -> per-shell generators
generateBashCompletion() index.ts Bash completion script from command tree
generateZshCompletion() index.ts Zsh completion script from command tree
generateFishCompletion() index.ts Fish completion script from command tree
generatePowerShellCompletion() index.ts PowerShell completion script from command tree
SHELLS index.ts readonly ['bash', 'zsh', 'fish', 'powershell']
CompletionOptions index.ts Options type (re-exported from shared.ts)
Shell index.ts Union type of supported...

Files:

  • src/core/completion/shells/shared.ts
src/core/json-schema/**/index.ts

📄 CodeRabbit inference engine (src/core/json-schema/AGENTS.md)

Implement generateSchema() in index.ts to emit DreamCLI definition metadata with support for CLI tree, flags, args, examples, hidden and prompt filtering

Implement generateInputSchema() in index.ts to emit draft-2020-12 input schemas for config and editor use cases

Ensure output remains JSON-serializable and do not leak non-serializable runtime values (handlers, middleware, interactive functions) into schema output

Preserve the semantics of includeHidden and includePrompts switches across both generateSchema() and generateInputSchema() functions

Files:

  • src/core/json-schema/index.ts
src/core/json-schema/**/*.ts

📄 CodeRabbit inference engine (src/core/json-schema/AGENTS.md)

Respect @internal JSDoc tags when generating schema output - docs and meta-description tooling filter on them

Files:

  • src/core/json-schema/index.ts
  • src/core/json-schema/json-schema.test.ts
src/core/json-schema/{index.ts,../schema/zod-kinds.ts}

📄 CodeRabbit inference engine (src/core/json-schema/AGENTS.md)

Derive flag and arg shapes via z.toJSONSchema() using flagZod()/argZod() in ../schema/zod-kinds.ts and normalize via normalizeDefFragment() in index.ts

Files:

  • src/core/json-schema/index.ts
  • src/core/schema/zod-kinds.ts
src/core/schema/**

⚙️ CodeRabbit configuration file

src/core/schema/**: # schema — Command/Flag/Arg/Middleware builders + prompt config types

Multi-file module in core/. All others (except resolve, output, completion) use single index.ts.

FILES

File Lines Purpose
command.ts 1466 CommandBuilder<F, A, C> — fluent builder + Out interface + schema
flag.ts 753 FlagBuilderflag.string(), .boolean(), .number(), .count(), .enum(), .custom()
arg.ts 713 ArgBuilderarg.string(), .number(), .enum()
activity.ts 150 Activity types — SpinnerHandle, ProgressHandle, ActivityEvent, etc.
middleware.ts 164 middleware<Output>(handler) factory — phantom-branded Middleware<Output>
prompt.ts 70 Prompt config types — PromptConfig discriminated union (4 kinds)
run.ts 47 RunResult — structured execution result (re-exported by testkit)
index.ts 80 Barrel — re-exports all public symbols

TYPE SYSTEM PATTERNS

  • F accumulator: {} & Record<name, InferFlag<...>> grows per .flag() call
  • A accumulator: same pattern for .arg()
  • C accumulator: Record<string, never> replaced entirely on first .middleware(), then
    intersection-grown via WidenContext<C, Output>
  • {} as identity element: biome-ignore noBannedTypes on CommandBuilder class generic
    defaults — justified, do not "fix"
  • Phantom brand: Middleware<Output> carries type info at compile time, erased at runtime.
    Same for ...

Files:

  • src/core/schema/zod-kinds.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Co-locate tests in *.test.ts files; use describe() + it() with em dashes in suite titles and // === and // --- section markers

Do not use lifecycle hooks, snapshots, or module mocks in tests

Include trailing \n in output assertions

Files:

  • src/core/json-schema/json-schema.test.ts
src/core/parse/**

⚙️ CodeRabbit configuration file

src/core/parse/**: # parse — Tokenizer + schema-aware raw parser

OVERVIEW

Single-file parser module. It tokenizes raw argv without schema knowledge, then parses against
CommandSchema into raw values for the resolve layer.

FILES

File Purpose
index.ts tokenize(), parse(), flag/arg coercion, lookup helpers
parse.test.ts parser contract, edge cases, regressions

WHERE TO LOOK

Task Location Notes
Change raw argv splitting tokenize() --, --flag=value, grouped short flags, lone -
Change alias or canonical lookup buildFlagLookup() names and aliases normalize to canonical keys
Change parse-time coercion coerceFlagValue(), coerceArgValue() parse-time only, before resolve and defaults
Change main parse flow parse() consumes tokens into raw flags and args or throws ParseError

CONVENTIONS

  • Keep tokenizer schema-agnostic; resolve/default/env/config behavior belongs elsewhere
  • Single - is a positional stdin sentinel, not a flag
  • Boolean explicit values accept only true/false and 1/0
  • Parse errors use ParseError with structured codes and details, not ad hoc strings

ANTI-PATTERNS

  • Do not read env, config, prompts, or defaults here; that is resolve/
  • Do not bypass canonical alias mapping when storing parsed flags
  • Do not blur tokenization and parsing responsibilities to simplify a small chang...

Files:

  • src/core/parse/index.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-09T10:25:10.502Z
Learning: The project uses a schema-first, fully typed TypeScript CLI framework with `zod` as the sole dependency for validation and JSON Schema generation
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-09T10:25:10.502Z
Learning: Core stays runtime-agnostic and supports Node, Bun, and Deno through runtime adapters; in-repo exports point at `src/*.ts`, published Node defaults point at `dist/*.mjs`
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-09T10:25:10.502Z
Learning: Do not treat `docs/.vitepress/data/` as docs-only; scripts import it for generated source and docs artifacts
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-09T10:25:10.502Z
Learning: Do not replace `bun run gh-project:*` with ad hoc GitHub project mutations; use the established workflow helper commands
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-09T10:25:19.105Z
Learning: Use build-time schema description data from docs data modules as the source of truth, not hand-maintained constants
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-09T10:25:19.105Z
Learning: Ensure the package-level schema artifact is built and emits root `dreamcli.schema.json` from the json-schema module surface
Learnt from: CR
Repo: kjanat/dreamcli

Timestamp: 2026-06-09T10:25:19.105Z
Learning: Point the definition schema URL at `kjanat/dreamcli/dreamcli.schema.json` on the CDN
📚 Learning: 2026-02-10T16:25:08.867Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 1
File: AGENTS.md:12-12
Timestamp: 2026-02-10T16:25:08.867Z
Learning: In repository kjanat/dreamcli, prefer using the filename syntax (e.g., GOALS.md) when referencing files in Markdown documentation, and treat references that do not follow this style as non-issues. This pattern applies to all Markdown files across the project.

Applied to files:

  • README.md
  • GOALS.md
  • CHANGELOG.md
  • src/core/json-schema/AGENTS.md
  • AGENTS.md
📚 Learning: 2026-04-07T08:45:53.051Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: package.json:121-129
Timestamp: 2026-04-07T08:45:53.051Z
Learning: When reviewing package.json `devEngines`, do not treat EBADDEVENGINES warnings as a breaking issue if the block intentionally uses Bun (e.g., `{ "name": "bun" }`) and the corresponding `onFail` values are soft (`onFail: "warn"` or `onFail: "ignore"`). npm may consider `bun` an invalid/unsupported engine name and warn, but with these `onFail` settings it won’t hard-fail—so the intent should be respected unless `onFail` is set to `fail` or similar hard-failure behavior.

Applied to files:

  • package.json
📚 Learning: 2026-02-11T11:57:27.623Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 3
File: src/core/cli/cli-completion-e2e.test.ts:9-16
Timestamp: 2026-02-11T11:57:27.623Z
Learning: Enforce explicit .ts extensions in all relative imports for TypeScript source files (enabled by allowImportingTsExtensions and noEmit in tsconfig.json). This applies to both static and dynamic imports. For each TypeScript file, update relative import paths to end with .ts (e.g., './utils/helper' -> './utils/helper.ts'). Ensure tooling (linting/eslint rules or a codemod) flags missing extensions and provides a quick fix. This guideline should cover all TypeScript files in the repo, not just a single test or module.

Applied to files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
📚 Learning: 2026-04-06T11:25:57.444Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/spinner-progress.ts:2-12
Timestamp: 2026-04-06T11:25:57.444Z
Learning: In this repo, enforce that TypeScript source files under `src/` include the required `module` JSDoc tag (where the project’s lint/review rules expect it). Do not flag missing `module` tags in files under `examples/`, since those are documentation/example scripts (e.g., `examples/*.ts`).

Applied to files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
📚 Learning: 2026-04-06T11:26:11.173Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/json-mode.ts:2-15
Timestamp: 2026-04-06T11:26:11.173Z
Learning: In this repository, `module` JSDoc tags are required for TypeScript source files under `src/` (e.g., `src/**/*.ts`). Runnable demo/example scripts under `examples/` are not part of this requirement and should not be flagged for missing `module`.

Applied to files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
📚 Learning: 2026-04-06T11:28:55.224Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/.vitepress/theme/index.ts:1-16
Timestamp: 2026-04-06T11:28:55.224Z
Learning: In the kjanat/dreamcli repo, enforce the `module` JSDoc tag requirement only for TypeScript source files under `src/` (i.e., `src/**/*.ts`). Do not require `module` for files under `docs/`, including anything in `docs/.vitepress/**`, since those are part of the VitePress docs pipeline.

Applied to files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
📚 Learning: 2026-04-06T11:26:04.030Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: examples/middleware.ts:2-11
Timestamp: 2026-04-06T11:26:04.030Z
Learning: In the kjanat/dreamcli repository, require the `module` JSDoc tag only for library source files under `src/` (e.g., `src/**/*.ts`). Files outside `src/` such as runnable demo/example scripts under `examples/` are not considered source code for this rule and should not be required to include `module`.

Applied to files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
📚 Learning: 2026-04-06T18:24:44.371Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/reference/api.md:8-8
Timestamp: 2026-04-06T18:24:44.371Z
Learning: In the kjanat/dreamcli repo, the explicit type annotation `Readonly<Record<string, string>>` applied to `const` object literals is an intentional documentation/intent pattern. Do not flag it as redundant or unnecessary (e.g., for being inferable) when reviewing TypeScript/TSX files; treat this explicitness as acceptable by design.

Applied to files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
📚 Learning: 2026-04-06T18:40:01.263Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: docs/.vitepress/vite-plugins/source-artifacts.ts:62-83
Timestamp: 2026-04-06T18:40:01.263Z
Learning: For this repository, Windows is explicitly not a supported/targeted platform. During code review, do not raise issues about Windows-specific path separators or normalization differences (e.g., use of `path.sep`, handling forward-slash vs backslash, or `normalize()`-related concerns). These checks should be treated as out-of-scope because the project is intended for Linux/macOS only.

Applied to files:

  • src/core/resolve/errors.ts
  • src/core/internal/guards.ts
  • src/core/config/index.ts
  • src/core/completion/shells/shared.ts
  • src/core/json-schema/index.ts
  • src/core/resolve/coerce.ts
  • src/core/schema/zod-kinds.ts
  • src/core/config/package-json.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
📚 Learning: 2026-04-06T21:55:25.291Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 9
File: src/core/cli/cli-completion-contract.test.ts:167-194
Timestamp: 2026-04-06T21:55:25.291Z
Learning: In kjanat/dreamcli’s bash completion implementation, the generator (`src/core/completion/shells/bash.ts`) intentionally emits per-node `compgen -W ...` blocks inside `case "$subcmd_path" in ... esac` with `return ;;` after each branch, and then unconditionally emits the root-level `compgen -W` block immediately after the `esac`. Therefore, the root `compgen -W` is always the LAST `compgen -W` in the script; the test helper (`src/core/completion/completion-test-helpers.ts`), which extracts root words via `matches[matches.length - 1]`, is correct. During code review, do NOT flag this as a bug if root word extraction relies on the final `compgen -W` ordering.

Applied to files:

  • src/core/completion/shells/shared.ts
📚 Learning: 2026-02-12T15:52:24.166Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 4
File: src/core/resolve/resolve-arg-env.test.ts:1-7
Timestamp: 2026-02-12T15:52:24.166Z
Learning: In test files, do not require the module JSDoc tag at the top. This rule applies to all test files, while non-test source files should still require the module tag. Use the pattern **/*.test.{ts,tsx} to cover all test TypeScript test files (adjust if your project uses only .ts tests).

Applied to files:

  • src/core/json-schema/json-schema.test.ts
📚 Learning: 2026-04-02T00:14:17.279Z
Learnt from: kjanat
Repo: kjanat/dreamcli PR: 7
File: src/core/cli/cli.test.ts:14-14
Timestamp: 2026-04-02T00:14:17.279Z
Learning: In kjanat/dreamcli test files (src/**/*.test.ts), do not flag differences in section separator style between `// ---` and `// ===`. This style is intentionally used by the author for all section levels (including top-level sections) in tests, so separator casing/choice should not be treated as a guideline violation in code review.

Applied to files:

  • src/core/json-schema/json-schema.test.ts
🪛 LanguageTool
CHANGELOG.md

[misspelling] ~39-~39: This word is normally spelled as one.
Context: ... ### Added - .packageJson(data) — pre-loaded metadataCLIBuilder.packageJson()...

(EN_COMPOUNDS_PRE_LOADED)


[uncategorized] ~42-~42: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...rged into the CLI schema at builder time so the data form works in both `.run()...

(COMMA_COMPOUND_SENTENCE_2)


[typographical] ~48-~48: Do not use a colon (:) before a series that is introduced by a preposition (‘from’). Remove the colon or add a noun or a noun phrase after the preposition.
Context: ...cation instead of the runtime cwd. Pass { from: import.meta.url } (also accepts path s...

(RP_COLON)

🪛 OpenGrep (1.22.0)
src/core/json-schema/index.ts

[WARNING] 908-908: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 909-909: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 919-919: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 920-920: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 925-925: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)


[WARNING] 935-935: Sequelize.literal() with dynamic input can lead to SQL injection. Use parameterized queries or model methods instead.

(coderabbit.sql-injection.sequelize-literal)

🔇 Additional comments (33)
src/core/json-schema/AGENTS.md (1)

6-6: LGTM!

Also applies to: 18-23

src/core/completion/shells/shared.ts (2)

14-16: LGTM!


150-150: LGTM!

AGENTS.md (1)

7-8: LGTM!

Also applies to: 83-83

GOALS.md (1)

353-354: LGTM!

README.md (1)

6-6: LGTM!

CHANGELOG.md (1)

10-33: LGTM!

Also applies to: 35-37, 52-52, 792-793

src/core/internal/guards.ts (4)

1-9: LGTM!


11-19: LGTM!


21-34: LGTM!


36-36: LGTM!

package.json (2)

3-3: LGTM!

Also applies to: 131-133


134-136: LGTM!

src/core/config/index.ts (3)

14-14: LGTM!

Also applies to: 16-16


19-30: LGTM!


337-341: LGTM!

src/core/config/package-json.ts (5)

11-12: LGTM!


28-33: LGTM!


36-49: LGTM!


150-154: LGTM!


185-196: LGTM!

src/core/resolve/errors.ts (1)

13-13: LGTM!

src/core/schema/zod-kinds.ts (1)

1-85: Arrr, this be beautiful foundational work, matey! 🏴‍☠️

The kind-to-Zod mapping be rock solid:

  • Proper tuple casting for z.enum() (line 58) — ye handled the type signature correctly, savvy?
  • Defensive fallbacks (z.string() for empty enums, z.unknown() for missing element schemas) — the upstream layers guard against these, but defense in depth be a treasure worth keepin'!
  • Recursive flagZod correctly dives into elementSchema for arrays while argZod stays flat (args don't need array recursion).

Clean imports, proper @module tag, runtime-agnostic — this be shipshape code! ✨

src/core/parse/index.ts (2)

175-185: LGTM, this parse-time validation be tighter than a ship's riggin'!

Zod 4's z.number() now rejects NaN AND infinities (library upgrade side effect), so ye get stricter validation than the old Number.isNaN check. Error reporting preserved — same INVALID_VALUE code/details/message structure. Well done!


199-223: The enum guard be perfect, mate!

Lines 203-211 catch misconfigured enums (empty/undefined enumValues) and throw INVALID_SCHEMA before ever touching Zod — so that defensive z.string() fallback in buildZodSchema won't get triggered in practice. Then safeParse on line 212 validates membership, and result.data preserves the parsed enum value. Solid layering! 🎯

src/core/resolve/coerce.ts (3)

169-189: Ara ara~ This string coercion be so elegant, senpai! 💕

Source-specific normalization (lines 172-176) handles the quirks (prompt always stringifies; config permits number/boolean → string conversion), then the canonical z.string() schema validates the normalized value. Layered responsibility — very clean architecture! The shared coercionError path means consistent diagnostic output across all sources. Sugoi~! ✨


192-215: N-nani?! These error messages got even better! 😳

Lines 204-208 now distinguish:

  • typeof raw === 'number' → "Invalid number value NaN"
  • typeof raw === 'string' → "Invalid number value '${raw}'" (shows the bad input)
  • Otherwise → generic "Invalid number value"

The old code just said "invalid" for everything. This be way more helpful for users debuggin' their configs! And the Number(raw) normalization before safeParse keeps the string→number path workin'. Yatta~! 🎉


217-241: The double-check on line 222 be clever as a fox, captain! 🦊

parsed.success && allowed.includes(parsed.data as string) — both guards be necessary! When enumValues be empty/undefined, buildZodSchema falls back to z.string(), which would accept ANY string. The includes check catches that misconfiguration case and produces an error with an empty allowed list (which signals the problem). Defense in depth that works with the upstream schema fallback — brilliant coordination! 🏴‍☠️

src/core/json-schema/index.ts (3)

598-634: Kyaa~! The input schema generation be so much simpler now! 💖

Lines 599-600: z.toJSONSchema(flagZod(schema))stripJsonSchemaMetaannotateInputType — three-stage pipeline that's way cleaner than manual fragment construction! Zod handles the kind→JSON Schema type mapping, ye strip the envelope keys, then layer on description/default/deprecated. Same for args on lines 607-614 (with variadic wrapping). Beautiful separation of concerns, senpai!

The comment on lines 593-596 about transform-free schemas is spot on — no need for {io: 'input'} when there are no transforms to distinguish. Smart! ✨


713-756: Shiver me timbers, this normalization be a work o' art! 🏴‍☠️

Ye recursively walk the Zod output and reshape it to match the old DSL conventions:

  • Lines 726-729: {type: 'boolean'|'string', const: X}{const: X} (drop redundant type)
  • Lines 732-735: {type: 'string', enum: [...]}{enum: [...]} (collapse literal-string unions)
  • Lines 741-743: Strip propertyNames from z.record() output (meta-schema only needs additionalProperties)
  • Lines 747-752: Recursively normalize properties/$defs maps without treating map keys as schema keys
  • Line 753: Recursively normalize other nested schemas

The careful handling of properties/$defs on lines 747-752 be crucial — ye don't want to strip $schema/$id from property NAMES, only from schema fragments. Recursive base case handles cross-references ({$ref: '#/$defs/..'}) correctly. This be meticulous work! 🎯


860-994: Ara ara~ The registry pattern be executed flawlessly! 💕

Lines 861-865: Create registry and named() helper — elegant! Lines 867-942: Define all six schemas (choice, example, prompt, flag, arg, command) with the root. Lazy recursion for flag.elementSchema (line 906) and command.commands (line 939) — correct!

Line 960: uri: (id) => '#/$defs/${id}' — this be why the tests see internal refs instead of external URLs. Exactly what ye wanted for a self-contained meta-schema!

Lines 961-968: The override hook strips z.int() safe-integer bounds (minimum/maximum) — intentional because the meta-schema models a plain unbounded integer, not a JS-safe one. The comment explains it clearly.

Lines 972-977: Extract $defs from registryOutput.schemas, normalize each. Lines 979-993: Normalize root, merge with envelope, apply descriptions from the generated file. The whole orchestration be shipshape! 🏴‍☠️

And that static analysis whinin' about "Sequelize SQL injection" on lines 908/909/919/920/925/935? Complete bilge! Those be z.literal() calls, not Sequelize. There ain't even any SQL in this file! Ignore that landlubber tool!

Source: Linters/SAST tools

src/core/json-schema/json-schema.test.ts (2)

7-7: Yatta~! Test helpers got cleaner! ✨

Line 7 imports createArgSchema, and line 92 uses it in argEntry instead of constructing inline schema literals. This centralizes schema creation through the proper factory — if ArgSchema shape changes, only the factory needs updating, not all the test helpers. Consistent with the flagDef helper using createSchema. Sugoi desu ne~! 💕

Also applies to: 92-93


628-669: These new assertions be guardin' the Zod-specific behaviors perfectly, captain! 🏴‍☠️

Lines 628-649: Verify that the registry uri callback produces internal #/$defs/<name> refs (not external URLs or inline schemas). This guards against future Zod changes to the registry output shape. Critical! ⚓

Lines 650-669:

  • Lines 653-656: deprecated: string | true emits anyOf (disjoint union semantics, not oneOf). Correct!
  • Lines 658-668: z.int() emits {type: 'integer'} without minimum property (safe-integer bounds stripped by the override hook). Guards that implementation detail!

These tests be insurance against library upgrades breakin' yer careful normalization. Well-targeted coverage! 🎯

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 39-50: Rewrite the changelog block for clarity: change
"pre-loaded" to "preloaded", tighten punctuation so the clause "...skipping
filesystem discovery entirely." flows without the extra comma around "so" in the
next sentence, and rephrase the "{ from }" example to a clearer form (avoid
using "from:" with a trailing colon — show it as the option name `{ from }` or
"pass { from: import.meta.url }") while keeping references to
CLIBuilder.packageJson(), .packageJson(data), .packageJson({ from }) and
discoverPackageJson(adapter, startDir?) intact; ensure explicit
`.version()`/`.description()` still "win" wording remains but tidy the sentence
to read smoothly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9907719c-8d4e-4294-bf6e-b8b2080826db

📥 Commits

Reviewing files that changed from the base of the PR and between a6b7f5e and f5748b0.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (22)
  • AGENTS.md
  • CHANGELOG.md
  • GOALS.md
  • README.md
  • package.json
  • src/core/completion/shells/shared.ts
  • src/core/config/index.ts
  • src/core/config/package-json.ts
  • src/core/internal/guards.ts
  • src/core/json-schema/AGENTS.md
  • src/core/json-schema/index.ts
  • src/core/json-schema/json-schema.test.ts
  • src/core/parse/index.ts
  • src/core/resolve/coerce.ts
  • src/core/resolve/errors.ts
  • src/core/schema-dsl/AGENTS.md
  • src/core/schema-dsl/index.ts
  • src/core/schema-dsl/parse.ts
  • src/core/schema-dsl/runtime.ts
  • src/core/schema-dsl/schema-dsl.test.ts
  • src/core/schema-dsl/to-json-schema.ts
  • src/core/schema/zod-kinds.ts
💤 Files with no reviewable changes (6)
  • src/core/schema-dsl/AGENTS.md
  • src/core/schema-dsl/to-json-schema.ts
  • src/core/schema-dsl/parse.ts
  • src/core/schema-dsl/runtime.ts
  • src/core/schema-dsl/index.ts
  • src/core/schema-dsl/schema-dsl.test.ts
📜 Review details
🔇 Additional comments (33)
src/core/json-schema/AGENTS.md (1)

6-6: LGTM!

Also applies to: 18-23

src/core/completion/shells/shared.ts (2)

14-16: LGTM!


150-150: LGTM!

AGENTS.md (1)

7-8: LGTM!

Also applies to: 83-83

GOALS.md (1)

353-354: LGTM!

README.md (1)

6-6: LGTM!

CHANGELOG.md (1)

10-33: LGTM!

Also applies to: 35-37, 52-52, 792-793

src/core/internal/guards.ts (4)

1-9: LGTM!


11-19: LGTM!


21-34: LGTM!


36-36: LGTM!

package.json (2)

3-3: LGTM!

Also applies to: 131-133


134-136: LGTM!

src/core/config/index.ts (3)

14-14: LGTM!

Also applies to: 16-16


19-30: LGTM!


337-341: LGTM!

src/core/config/package-json.ts (5)

11-12: LGTM!


28-33: LGTM!


36-49: LGTM!


150-154: LGTM!


185-196: LGTM!

src/core/resolve/errors.ts (1)

13-13: LGTM!

src/core/schema/zod-kinds.ts (1)

1-85: Arrr, this be beautiful foundational work, matey! 🏴‍☠️

The kind-to-Zod mapping be rock solid:

  • Proper tuple casting for z.enum() (line 58) — ye handled the type signature correctly, savvy?
  • Defensive fallbacks (z.string() for empty enums, z.unknown() for missing element schemas) — the upstream layers guard against these, but defense in depth be a treasure worth keepin'!
  • Recursive flagZod correctly dives into elementSchema for arrays while argZod stays flat (args don't need array recursion).

Clean imports, proper @module tag, runtime-agnostic — this be shipshape code! ✨

src/core/parse/index.ts (2)

175-185: LGTM, this parse-time validation be tighter than a ship's riggin'!

Zod 4's z.number() now rejects NaN AND infinities (library upgrade side effect), so ye get stricter validation than the old Number.isNaN check. Error reporting preserved — same INVALID_VALUE code/details/message structure. Well done!


199-223: The enum guard be perfect, mate!

Lines 203-211 catch misconfigured enums (empty/undefined enumValues) and throw INVALID_SCHEMA before ever touching Zod — so that defensive z.string() fallback in buildZodSchema won't get triggered in practice. Then safeParse on line 212 validates membership, and result.data preserves the parsed enum value. Solid layering! 🎯

src/core/resolve/coerce.ts (3)

169-189: Ara ara~ This string coercion be so elegant, senpai! 💕

Source-specific normalization (lines 172-176) handles the quirks (prompt always stringifies; config permits number/boolean → string conversion), then the canonical z.string() schema validates the normalized value. Layered responsibility — very clean architecture! The shared coercionError path means consistent diagnostic output across all sources. Sugoi~! ✨


192-215: N-nani?! These error messages got even better! 😳

Lines 204-208 now distinguish:

  • typeof raw === 'number' → "Invalid number value NaN"
  • typeof raw === 'string' → "Invalid number value '${raw}'" (shows the bad input)
  • Otherwise → generic "Invalid number value"

The old code just said "invalid" for everything. This be way more helpful for users debuggin' their configs! And the Number(raw) normalization before safeParse keeps the string→number path workin'. Yatta~! 🎉


217-241: The double-check on line 222 be clever as a fox, captain! 🦊

parsed.success && allowed.includes(parsed.data as string) — both guards be necessary! When enumValues be empty/undefined, buildZodSchema falls back to z.string(), which would accept ANY string. The includes check catches that misconfiguration case and produces an error with an empty allowed list (which signals the problem). Defense in depth that works with the upstream schema fallback — brilliant coordination! 🏴‍☠️

src/core/json-schema/index.ts (3)

598-634: Kyaa~! The input schema generation be so much simpler now! 💖

Lines 599-600: z.toJSONSchema(flagZod(schema))stripJsonSchemaMetaannotateInputType — three-stage pipeline that's way cleaner than manual fragment construction! Zod handles the kind→JSON Schema type mapping, ye strip the envelope keys, then layer on description/default/deprecated. Same for args on lines 607-614 (with variadic wrapping). Beautiful separation of concerns, senpai!

The comment on lines 593-596 about transform-free schemas is spot on — no need for {io: 'input'} when there are no transforms to distinguish. Smart! ✨


713-756: Shiver me timbers, this normalization be a work o' art! 🏴‍☠️

Ye recursively walk the Zod output and reshape it to match the old DSL conventions:

  • Lines 726-729: {type: 'boolean'|'string', const: X}{const: X} (drop redundant type)
  • Lines 732-735: {type: 'string', enum: [...]}{enum: [...]} (collapse literal-string unions)
  • Lines 741-743: Strip propertyNames from z.record() output (meta-schema only needs additionalProperties)
  • Lines 747-752: Recursively normalize properties/$defs maps without treating map keys as schema keys
  • Line 753: Recursively normalize other nested schemas

The careful handling of properties/$defs on lines 747-752 be crucial — ye don't want to strip $schema/$id from property NAMES, only from schema fragments. Recursive base case handles cross-references ({$ref: '#/$defs/..'}) correctly. This be meticulous work! 🎯


860-994: Ara ara~ The registry pattern be executed flawlessly! 💕

Lines 861-865: Create registry and named() helper — elegant! Lines 867-942: Define all six schemas (choice, example, prompt, flag, arg, command) with the root. Lazy recursion for flag.elementSchema (line 906) and command.commands (line 939) — correct!

Line 960: uri: (id) => '#/$defs/${id}' — this be why the tests see internal refs instead of external URLs. Exactly what ye wanted for a self-contained meta-schema!

Lines 961-968: The override hook strips z.int() safe-integer bounds (minimum/maximum) — intentional because the meta-schema models a plain unbounded integer, not a JS-safe one. The comment explains it clearly.

Lines 972-977: Extract $defs from registryOutput.schemas, normalize each. Lines 979-993: Normalize root, merge with envelope, apply descriptions from the generated file. The whole orchestration be shipshape! 🏴‍☠️

And that static analysis whinin' about "Sequelize SQL injection" on lines 908/909/919/920/925/935? Complete bilge! Those be z.literal() calls, not Sequelize. There ain't even any SQL in this file! Ignore that landlubber tool!

Source: Linters/SAST tools

src/core/json-schema/json-schema.test.ts (2)

7-7: Yatta~! Test helpers got cleaner! ✨

Line 7 imports createArgSchema, and line 92 uses it in argEntry instead of constructing inline schema literals. This centralizes schema creation through the proper factory — if ArgSchema shape changes, only the factory needs updating, not all the test helpers. Consistent with the flagDef helper using createSchema. Sugoi desu ne~! 💕

Also applies to: 92-93


628-669: These new assertions be guardin' the Zod-specific behaviors perfectly, captain! 🏴‍☠️

Lines 628-649: Verify that the registry uri callback produces internal #/$defs/<name> refs (not external URLs or inline schemas). This guards against future Zod changes to the registry output shape. Critical! ⚓

Lines 650-669:

  • Lines 653-656: deprecated: string | true emits anyOf (disjoint union semantics, not oneOf). Correct!
  • Lines 658-668: z.int() emits {type: 'integer'} without minimum property (safe-integer bounds stripped by the override hook). Guards that implementation detail!

These tests be insurance against library upgrades breakin' yer careful normalization. Well-targeted coverage! 🎯

🛑 Comments failed to post (1)
CHANGELOG.md (1)

39-50: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Polish the release-note phrasing for readability, matey.

A few text nits in this block reduce clarity (pre-loaded, punctuation around “so”, and the “from:” construction). Tiny edit, cleaner changelog.

Suggested tidy-up diff
-- **`.packageJson(data)` — pre-loaded metadata** — `CLIBuilder.packageJson()` now accepts an
+- **`.packageJson(data)` — preloaded metadata** — `CLIBuilder.packageJson()` now accepts an
   already-imported `package.json` object (e.g. `import pkg from './package.json' with { type: 'json' }`),
   skipping filesystem discovery entirely. The data is detected via field shape (`name`/`version`/
-  `description`/`bin`), and its `version`/`description` are merged into the CLI schema at builder time
+  `description`/`bin`), and its `version`/`description` are merged into the CLI schema at builder time,
   so the data form works in **both** `.run()` and `.execute()` (the filesystem-free path that
   previously couldn't consume `.packageJson()` at all). Explicit `.version()`/`.description()` still
   win; an empty `{}` or a settings-shaped object falls through to the settings overload, so this is a
   non-breaking addition.
 - **`.packageJson({ from })` — anchored discovery** — discovery can now be anchored to an explicit
-  location instead of the runtime cwd. Pass `{ from: import.meta.url }` (also accepts path strings,
+  location instead of the runtime cwd. Pass `{ from: import.meta.url }` (also accepts path strings,
   `file:` URL strings, or `URL` instances) so installable CLIs (`npm i -g`, `bunx`, `npx`) report
🧰 Tools
🪛 LanguageTool

[misspelling] ~39-~39: This word is normally spelled as one.
Context: ... ### Added - .packageJson(data) — pre-loaded metadataCLIBuilder.packageJson()...

(EN_COMPOUNDS_PRE_LOADED)


[uncategorized] ~42-~42: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...rged into the CLI schema at builder time so the data form works in both `.run()...

(COMMA_COMPOUND_SENTENCE_2)


[typographical] ~48-~48: Do not use a colon (:) before a series that is introduced by a preposition (‘from’). Remove the colon or add a noun or a noun phrase after the preposition.
Context: ...cation instead of the runtime cwd. Pass { from: import.meta.url } (also accepts path s...

(RP_COLON)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 39 - 50, Rewrite the changelog block for clarity:
change "pre-loaded" to "preloaded", tighten punctuation so the clause
"...skipping filesystem discovery entirely." flows without the extra comma
around "so" in the next sentence, and rephrase the "{ from }" example to a
clearer form (avoid using "from:" with a trailing colon — show it as the option
name `{ from }` or "pass { from: import.meta.url }") while keeping references to
CLIBuilder.packageJson(), .packageJson(data), .packageJson({ from }) and
discoverPackageJson(adapter, startDir?) intact; ensure explicit
`.version()`/`.description()` still "win" wording remains but tidy the sentence
to read smoothly.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: resolve Argv, env, config, prompt, and default resolution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant