Skip to content

Add CLI#785

Open
ericglau wants to merge 22 commits intoOpenZeppelin:masterfrom
ericglau:contracts-cli
Open

Add CLI#785
ericglau wants to merge 22 commits intoOpenZeppelin:masterfrom
ericglau:contracts-cli

Conversation

@ericglau
Copy link
Copy Markdown
Member

@ericglau ericglau commented Mar 27, 2026

Adds a new @openzeppelin/contracts-cli package that generates smart contracts from the command line for all supported languages and contract kinds.

Schemas are shared with the MCP package via a new @openzeppelin/wizard-common/schemas subpath export.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

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 UI

Review profile: CHILL

Plan: Pro

Run ID: 2f11180b-520f-41ef-b66b-f1a6eb05ff19

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:

  • 🔍 Trigger review

Walkthrough

This PR introduces a new CLI package for OpenZeppelin contracts, centralizes Zod schemas into @openzeppelin/wizard-common with a new subpath export (./schemas), updates MCP tools to consume those centralized schemas, adds a circular dependency check script, and updates CI workflows.

Changes

Cohort / File(s) Summary
New CLI Package
packages/cli/*
Introduces @openzeppelin/contracts-cli with schema-driven argument parsing and command registry. Includes cli-adapter.ts implementing Zod introspection for help generation and argv parsing; registry.ts mapping command names to schema/print functions; index.ts as the executable entrypoint; and comprehensive test suites validating CLI parsing and output across all contract types.
Schema Centralization
packages/common/src/ai/schemas/*
Renames all schema exports with language/domain prefixes (e.g., commonSchemasolidityCommonSchema), makes Cairo access field optional, moves Uniswap hooks descriptions from prompt to field-level, and creates new index.ts aggregating all schema exports. Updated package.json to add exports field restricting access to declared subpaths (. and ./schemas).
Schema Description Updates
packages/common/src/ai/descriptions/uniswap-hooks.ts
Shortens main hook prompt to a single sentence and relocates enumerated hook descriptions to field-level describe() calls on the --hook parameter.
MCP Tool Schema Imports
packages/mcp/src/{solidity,cairo,stellar,stylus,confidential,uniswap-hooks}/tools/*
Updates 40+ tool files (both .ts and .test.ts) to import renamed schemas from @openzeppelin/wizard-common/schemas instead of local modules (e.g., accountSchemasolidityAccountSchema from common).
Changesets and Skill Documentation
.changeset/add-cli-package.md, .changeset/mcp-use-common-schemas.md, .changeset/move-schemas-to-common.md, .claude/skills/changeset/SKILL.md
Adds changesets documenting CLI minor release, MCP patch for schema reuse, and common package minor release with breaking export changes; also documents changeset creation conventions.
CI/CD and Utilities
.github/workflows/test.yml, scripts/check-circular-deps.mjs, package.json, .gitignore
Renames format-lint job to static-checks, adds circular dependency check step and new cli test job; introduces check:circular-deps npm script performing DFS-based cycle detection; adds packages/cli to workspaces; updates .gitignore to track .claude/skills/ while ignoring other .claude/ content.

Sequence Diagram

sequenceDiagram
    actor User as User (CLI)
    participant CLI as index.ts (Entrypoint)
    participant Parser as cli-adapter.ts<br/>(Parser)
    participant Registry as registry.ts<br/>(Registry)
    participant Generator as Wizard Module<br/>(print function)
    participant Stdout as stdout

    User->>CLI: contracts-cli solidity-erc20 --name=MyToken
    CLI->>CLI: Parse process.argv
    alt --help or no args
        CLI->>Registry: Get available commands
        CLI->>Parser: generateHelp(...)
        CLI->>Stdout: Print usage
        CLI->>CLI: Exit 0
    else Valid command
        CLI->>Registry: registry[command]
        Registry-->>CLI: RegistryEntry
        alt --help detected
            CLI->>Parser: generateHelp(command, schema)
            CLI->>Stdout: Print command help
            CLI->>CLI: Exit 0
        else Normal execution
            CLI->>Parser: parseArgsFromSchema(schema, argv)
            Parser->>Parser: Introspect schema shape
            Parser->>Parser: Extract flags metadata
            Parser->>Parser: Parse argv into nested object
            Parser->>Parser: Validate via z.object(schema)
            Parser-->>CLI: Parsed options
            CLI->>Registry: entry.run(argv)
            Registry->>Generator: print(parsed_options)
            Generator-->>Registry: Code string
            Registry-->>CLI: Code string
            CLI->>Stdout: Write code
            CLI->>CLI: Exit 0
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

The PR spans 70+ files with heterogeneous changes: a new CLI package with non-trivial schema introspection/parsing logic, systematic schema renaming/reorganization affecting 40+ MCP tool files, package export changes introducing breaking updates, and multiple configuration/workflow updates. While many MCP changes are repetitive (import swaps), the CLI adapter requires careful logic review, and the schema refactoring introduces breaking API changes warranting thorough validation.

Possibly related PRs

  • Prepare Release #709: Modifies and re-exports schemas in packages/common, directly overlapping with the schema centralization and AI description changes in this PR.
  • Add Confidential tab #652: Adds Confidential package and MCP tools consuming shared schemas from @openzeppelin/wizard-common, complementing the schema export surface introduced here.
  • Hooks Wizard v0.0.1 #628: Introduces the Uniswap Hooks package and its schemas, which this PR refactors and re-exports under the new common schema subpath.

Suggested reviewers

  • CoveMB
  • pasevin
🚥 Pre-merge checks | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Add CLI' is vague and generic, using minimal descriptive terms that don't convey meaningful information about the specific changes in the changeset. Consider a more descriptive title that captures the main purpose, such as 'Add CLI package for contract code generation' or 'Introduce @openzeppelin/contracts-cli package with schema-driven command registry'.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess whether the description relates to the changeset. Add a pull request description that explains the purpose of adding the CLI package, its integration with the monorepo, and how it uses the shared schema infrastructure.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@ericglau ericglau marked this pull request as ready for review March 27, 2026 19:56
@ericglau ericglau requested a review from a team as a code owner March 27, 2026 19:56
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (6)
packages/common/src/ai/descriptions/uniswap-hooks.ts (1)

48-50: Consider removing hardcoded leading spaces in generated bullets.

The current - ... formatting can produce overly indented help text depending on renderer; using plain - is usually safer.

✂️ Suggested adjustment
-  hook: `The name of the Uniswap hook. Available hooks:\n${Object.entries(byHooksDescriptions)
-    .map(([name, desc]) => `        - ${name}: ${desc}`)
+  hook: `The name of the Uniswap hook. Available hooks:\n${Object.entries(byHooksDescriptions)
+    .map(([name, desc]) => `- ${name}: ${desc}`)
     .join('\n')}`,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/ai/descriptions/uniswap-hooks.ts` around lines 48 - 50,
The hook help string in the hook property builds bullets with hardcoded leading
spaces ("        - ${name}: ${desc}") which can cause excessive indentation;
update the template in the hook construction that maps over byHooksDescriptions
to use a plain "- ${name}: ${desc}" (no leading spaces) so bullets render
consistently across consumers (look for the hook template that references
byHooksDescriptions and change the mapped string and join accordingly).
packages/common/src/ai/schemas/cairo.ts (1)

109-111: Optional: deduplicate repeated common field picks.

upgradeable/info/macros are repeated across several schemas; extracting a small shared object would reduce maintenance overhead.

Also applies to: 117-119, 138-142, 151-152

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

In `@packages/common/src/ai/schemas/cairo.ts` around lines 109 - 111, Several
schemas repeatedly pick cairoCommonSchema.upgradeable, .info, and .macros;
extract these into a single shared object (e.g., const cairoSharedFields = {
upgradeable: cairoCommonSchema.upgradeable, info: cairoCommonSchema.info,
macros: cairoCommonSchema.macros }) and replace the repeated property lists by
spreading or merging cairoSharedFields into each schema (locations referencing
cairoCommonSchema.upgradeable/info/macros such as the blocks around the current
picks and the other occurrences you noted). Update any exports/imports as needed
so all schemas use the new cairoSharedFields to avoid duplication and reduce
maintenance overhead.
packages/common/package.json (1)

9-17: Consider adding types field to exports for TypeScript ESM consumers.

While typesVersions works for many cases, modern TypeScript ESM projects may benefit from explicit types conditions in the exports field for better type resolution:

"exports": {
  ".": {
    "types": "./dist/index.d.ts",
    "default": "./dist/index.js"
  },
  "./schemas": {
    "types": "./dist/ai/schemas/index.d.ts",
    "default": "./dist/ai/schemas/index.js"
  }
}

This provides more explicit type resolution for consumers using moduleResolution: "bundler" or "node16".

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

In `@packages/common/package.json` around lines 9 - 17, Update the package.json
"exports" entries to include explicit "types" conditions alongside the current
JS paths so TypeScript ESM consumers can find declarations; specifically change
the "." export to an object with "types": "dist/index.d.ts" and "default":
"dist/index.js", and change the "./schemas" export to an object with "types":
"dist/ai/schemas/index.d.ts" and "default": "dist/ai/schemas/index.js" (keep or
remove typesVersions as desired). Locate and modify the "exports" block and
ensure the referenced declaration files exist at the specified paths.
packages/cli/src/cli-adapter.ts (1)

117-121: Consider explicit number validation for better error messages.

Number(value) returns NaN for non-numeric strings. While Zod's safeParse will catch this, the error message may be confusing (e.g., "Expected number, received nan"). Consider validating before conversion:

🔧 Suggested improvement
 function parseFlagValue(spec: FlagSpec, value: string): string | number | boolean {
-  if (spec.type === 'number') return Number(value);
+  if (spec.type === 'number') {
+    const num = Number(value);
+    if (Number.isNaN(num)) {
+      throw new Error(`Invalid number for --${spec.name}: ${value}`);
+    }
+    return num;
+  }
   if (spec.hasLiteralFalse && value === 'false') return false;
   return value;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/cli-adapter.ts` around lines 117 - 121, The parseFlagValue
function currently converts numeric flags with Number(value) which yields NaN
for invalid numeric input; update parseFlagValue to explicitly validate the
string before conversion when spec.type === 'number' (e.g., using a
numeric-regex or Number.isFinite(Number(value))) and if invalid, surface a
clear, descriptive error (include the flag identifier from FlagSpec if
available) instead of returning NaN—otherwise safely return the parsed number;
keep the checks around spec.hasLiteralFalse unchanged.
packages/cli/src/cli.test.ts (1)

54-73: Registry completeness test provides good coverage.

This test ensures every kind discovered in core wizard packages has a corresponding CLI registry entry. The approach of parsing kind.ts files directly is clever for catching missing commands.

Consider adding a try-catch around the readFile call (line 62) to provide a clearer error message if a kind.ts file is missing for a core directory, rather than letting the test fail with a generic ENOENT error.

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

In `@packages/cli/src/cli.test.ts` around lines 54 - 73, Wrap the readFile call
that loads each core package's kind.ts in a try-catch to surface a clearer
failure when a file is missing: around the readFile(join(PACKAGES_CORE_PATH,
coreDir, 'src', 'kind.ts'), 'utf-8') invocation in the test that uses
readdir/coreDirs, catch errors and call t.fail or throw a new Error that
includes the coreDir and the full path (and the original error message) so the
test output states which core language is missing its kind.ts; keep the rest of
the logic using kindsFromSource and coreKindToCommand unchanged.
packages/common/src/ai/schemas/schemas.test.ts (1)

42-70: Potential for both t.fail() and t.pass() to be called in nested schema validation.

When a nested ZodObject field fails validation in the recursive call (line 59), t.fail() is called and that recursive frame returns, but the outer loop continues via continue at line 60. If all remaining top-level fields pass, t.pass() at line 69 will also be called. Depending on AVA's behavior, this may mask failures or cause unexpected test outcomes.

Consider tracking failure state and returning early from the outer function:

♻️ Proposed fix
 function assertAllFieldsHaveDescriptions(
   t: { pass: () => void; fail: (msg: string) => void },
   shape: z.ZodRawShape,
   prefix = '',
-) {
+): boolean {
   for (const [key, schema] of Object.entries(shape)) {
     const zodSchema = schema as z.ZodTypeAny;
     const fullKey = prefix ? `${prefix}.${key}` : key;

     // Unwrap optional to check inner type
     let innerSchema = zodSchema;
     if (innerSchema._def.typeName === 'ZodOptional') {
       innerSchema = innerSchema._def.innerType as z.ZodTypeAny;
     }

     // For ZodObject fields, recurse into inner fields (the object itself may or may not have a description)
     if (innerSchema._def.typeName === 'ZodObject') {
-      assertAllFieldsHaveDescriptions(t, (innerSchema as z.ZodObject<z.ZodRawShape>).shape, fullKey);
-      continue;
+      if (!assertAllFieldsHaveDescriptions(t, (innerSchema as z.ZodObject<z.ZodRawShape>).shape, fullKey)) {
+        return false;
+      }
+      continue;
     }

     const desc = zodSchema.description ?? zodSchema._def?.innerType?.description;
     if (!desc) {
       t.fail(`Field "${fullKey}" is missing a .describe() string`);
-      return;
+      return false;
     }
   }
   t.pass();
+  return true;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/ai/schemas/schemas.test.ts` around lines 42 - 70, The
recursive assertAllFieldsHaveDescriptions may call t.fail() in a nested call but
still proceed to call t.pass() at the end; change the function to short-circuit
on failures by returning a boolean (or throw) from
assertAllFieldsHaveDescriptions so callers can detect failure: when you call
assertAllFieldsHaveDescriptions recursively from inside the ZodObject branch,
check its return value and immediately return false if it failed; similarly,
whenever you call t.fail(...) return false right away; only call t.pass() when
the function is about to return true (no failures). Update the
assertAllFieldsHaveDescriptions signature and all call sites accordingly (use
the function name assertAllFieldsHaveDescriptions and the recursive call site
currently invoking it).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/changeset/SKILL.md:
- Around line 26-28: Replace the inline code spans that contain internal
trailing spaces (e.g., the `` `- ` `` example) with lint-safe wording: write the
first bullet as a plain sentence (no leading dash), describe subsequent items
using a literal hyphen dash but not wrapped in an inline code span (use "- "
wording), and specify breaking changes using "- **Breaking change**:" (or "-
**Breaking changes**:" with sub-items indented using "  - "). Update the text
around "First line", "Subsequent lines", and "Breaking changes" in SKILL.md to
remove any backticked examples that include internal spaces and instead use the
plain text phrasing described above so MD038 is not triggered.

In `@packages/cli/src/cli-adapter.ts`:
- Around line 21-35: unwrapSchema currently relies on internal Zod internals
(_def.innerType and _def.schema) which will break on Zod 4; add integration
tests for the unwrapSchema function that cover ZodOptional, ZodNullable,
ZodDefault and ZodEffects inputs (using the unwrapSchema symbol) to lock
expected behavior into CI, and replace the internal _def accesses before
upgrading by refactoring unwrapSchema to use only public Zod APIs or documented
helper methods (do the tests first so CI will catch regressions when you
refactor or upgrade).

In `@scripts/check-circular-deps.mjs`:
- Around line 25-27: The catch block that currently swallows all errors when
reading/parsing package.json should not ignore malformed-JSON or other real
errors; update the error handling around the package.json read/JSON.parse (the
try/catch that currently has "catch { // no package.json in this dir }") to only
treat "file not found" (ENOENT) as a silent case and rethrow or log any other
errors (e.g., JSON parse errors) including the filename and error details so
invalid package.json is surfaced rather than hidden.

---

Nitpick comments:
In `@packages/cli/src/cli-adapter.ts`:
- Around line 117-121: The parseFlagValue function currently converts numeric
flags with Number(value) which yields NaN for invalid numeric input; update
parseFlagValue to explicitly validate the string before conversion when
spec.type === 'number' (e.g., using a numeric-regex or
Number.isFinite(Number(value))) and if invalid, surface a clear, descriptive
error (include the flag identifier from FlagSpec if available) instead of
returning NaN—otherwise safely return the parsed number; keep the checks around
spec.hasLiteralFalse unchanged.

In `@packages/cli/src/cli.test.ts`:
- Around line 54-73: Wrap the readFile call that loads each core package's
kind.ts in a try-catch to surface a clearer failure when a file is missing:
around the readFile(join(PACKAGES_CORE_PATH, coreDir, 'src', 'kind.ts'),
'utf-8') invocation in the test that uses readdir/coreDirs, catch errors and
call t.fail or throw a new Error that includes the coreDir and the full path
(and the original error message) so the test output states which core language
is missing its kind.ts; keep the rest of the logic using kindsFromSource and
coreKindToCommand unchanged.

In `@packages/common/package.json`:
- Around line 9-17: Update the package.json "exports" entries to include
explicit "types" conditions alongside the current JS paths so TypeScript ESM
consumers can find declarations; specifically change the "." export to an object
with "types": "dist/index.d.ts" and "default": "dist/index.js", and change the
"./schemas" export to an object with "types": "dist/ai/schemas/index.d.ts" and
"default": "dist/ai/schemas/index.js" (keep or remove typesVersions as desired).
Locate and modify the "exports" block and ensure the referenced declaration
files exist at the specified paths.

In `@packages/common/src/ai/descriptions/uniswap-hooks.ts`:
- Around line 48-50: The hook help string in the hook property builds bullets
with hardcoded leading spaces ("        - ${name}: ${desc}") which can cause
excessive indentation; update the template in the hook construction that maps
over byHooksDescriptions to use a plain "- ${name}: ${desc}" (no leading spaces)
so bullets render consistently across consumers (look for the hook template that
references byHooksDescriptions and change the mapped string and join
accordingly).

In `@packages/common/src/ai/schemas/cairo.ts`:
- Around line 109-111: Several schemas repeatedly pick
cairoCommonSchema.upgradeable, .info, and .macros; extract these into a single
shared object (e.g., const cairoSharedFields = { upgradeable:
cairoCommonSchema.upgradeable, info: cairoCommonSchema.info, macros:
cairoCommonSchema.macros }) and replace the repeated property lists by spreading
or merging cairoSharedFields into each schema (locations referencing
cairoCommonSchema.upgradeable/info/macros such as the blocks around the current
picks and the other occurrences you noted). Update any exports/imports as needed
so all schemas use the new cairoSharedFields to avoid duplication and reduce
maintenance overhead.

In `@packages/common/src/ai/schemas/schemas.test.ts`:
- Around line 42-70: The recursive assertAllFieldsHaveDescriptions may call
t.fail() in a nested call but still proceed to call t.pass() at the end; change
the function to short-circuit on failures by returning a boolean (or throw) from
assertAllFieldsHaveDescriptions so callers can detect failure: when you call
assertAllFieldsHaveDescriptions recursively from inside the ZodObject branch,
check its return value and immediately return false if it failed; similarly,
whenever you call t.fail(...) return false right away; only call t.pass() when
the function is about to return true (no failures). Update the
assertAllFieldsHaveDescriptions signature and all call sites accordingly (use
the function name assertAllFieldsHaveDescriptions and the recursive call site
currently invoking it).
🪄 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 UI

Review profile: CHILL

Plan: Pro

Run ID: 8d7376eb-94a5-4066-bb18-417d2f9ed1fc

📥 Commits

Reviewing files that changed from the base of the PR and between 5eec825 and 8efdbca.

⛔ Files ignored due to path filters (2)
  • packages/cli/src/cli.test.ts.snap is excluded by !**/*.snap
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (79)
  • .changeset/add-cli-package.md
  • .changeset/mcp-use-common-schemas.md
  • .changeset/move-schemas-to-common.md
  • .claude/skills/changeset/SKILL.md
  • .github/workflows/test.yml
  • .gitignore
  • package.json
  • packages/cli/LICENSE
  • packages/cli/NOTICE
  • packages/cli/ava.config.js
  • packages/cli/package.json
  • packages/cli/src/cli-adapter.ts
  • packages/cli/src/cli-options.test.ts
  • packages/cli/src/cli.test.ts
  • packages/cli/src/cli.test.ts.md
  • packages/cli/src/index.ts
  • packages/cli/src/registry.ts
  • packages/cli/tsconfig.json
  • packages/common/ava.config.js
  • packages/common/package.json
  • packages/common/src/ai/descriptions/uniswap-hooks.ts
  • packages/common/src/ai/schemas/cairo.ts
  • packages/common/src/ai/schemas/confidential.ts
  • packages/common/src/ai/schemas/index.ts
  • packages/common/src/ai/schemas/schemas.test.ts
  • packages/common/src/ai/schemas/solidity.ts
  • packages/common/src/ai/schemas/stellar.ts
  • packages/common/src/ai/schemas/stylus.ts
  • packages/common/src/ai/schemas/uniswap-hooks.ts
  • packages/common/tsconfig.json
  • packages/mcp/src/cairo/tools/account.test.ts
  • packages/mcp/src/cairo/tools/account.ts
  • packages/mcp/src/cairo/tools/custom.test.ts
  • packages/mcp/src/cairo/tools/custom.ts
  • packages/mcp/src/cairo/tools/erc1155.test.ts
  • packages/mcp/src/cairo/tools/erc1155.ts
  • packages/mcp/src/cairo/tools/erc20.test.ts
  • packages/mcp/src/cairo/tools/erc20.ts
  • packages/mcp/src/cairo/tools/erc721.test.ts
  • packages/mcp/src/cairo/tools/erc721.ts
  • packages/mcp/src/cairo/tools/governor.test.ts
  • packages/mcp/src/cairo/tools/governor.ts
  • packages/mcp/src/cairo/tools/multisig.test.ts
  • packages/mcp/src/cairo/tools/multisig.ts
  • packages/mcp/src/cairo/tools/vesting.test.ts
  • packages/mcp/src/cairo/tools/vesting.ts
  • packages/mcp/src/confidential/tools/erc7984.test.ts
  • packages/mcp/src/confidential/tools/erc7984.ts
  • packages/mcp/src/solidity/tools/account.test.ts
  • packages/mcp/src/solidity/tools/account.ts
  • packages/mcp/src/solidity/tools/custom.test.ts
  • packages/mcp/src/solidity/tools/custom.ts
  • packages/mcp/src/solidity/tools/erc1155.test.ts
  • packages/mcp/src/solidity/tools/erc1155.ts
  • packages/mcp/src/solidity/tools/erc20.test.ts
  • packages/mcp/src/solidity/tools/erc20.ts
  • packages/mcp/src/solidity/tools/erc721.test.ts
  • packages/mcp/src/solidity/tools/erc721.ts
  • packages/mcp/src/solidity/tools/governor.test.ts
  • packages/mcp/src/solidity/tools/governor.ts
  • packages/mcp/src/solidity/tools/rwa.test.ts
  • packages/mcp/src/solidity/tools/rwa.ts
  • packages/mcp/src/solidity/tools/stablecoin.test.ts
  • packages/mcp/src/solidity/tools/stablecoin.ts
  • packages/mcp/src/stellar/tools/fungible.test.ts
  • packages/mcp/src/stellar/tools/fungible.ts
  • packages/mcp/src/stellar/tools/non-fungible.test.ts
  • packages/mcp/src/stellar/tools/non-fungible.ts
  • packages/mcp/src/stellar/tools/stablecoin.test.ts
  • packages/mcp/src/stellar/tools/stablecoin.ts
  • packages/mcp/src/stylus/tools/erc1155.test.ts
  • packages/mcp/src/stylus/tools/erc1155.ts
  • packages/mcp/src/stylus/tools/erc20.test.ts
  • packages/mcp/src/stylus/tools/erc20.ts
  • packages/mcp/src/stylus/tools/erc721.test.ts
  • packages/mcp/src/stylus/tools/erc721.ts
  • packages/mcp/src/uniswap-hooks/tools/hooks.test.ts
  • packages/mcp/src/uniswap-hooks/tools/hooks.ts
  • scripts/check-circular-deps.mjs

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
CONTRIBUTING.md (1)

10-10: Optional wording polish for list consistency/readability.

This is correct as written; if you want to satisfy the style warning, you can vary the sentence start (e.g., “packages/cli provides the CLI interface”).

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

In `@CONTRIBUTING.md` at line 10, Update the list item for `packages/cli` to use
consistent wording by rephrasing it to something like "`packages/cli` provides
the CLI" (or similar phrasing such as "contains the CLI interface") to satisfy
the style warning while preserving meaning; edit the `packages/cli` list entry
in CONTRIBUTING.md to use the new wording.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@CONTRIBUTING.md`:
- Line 10: Update the list item for `packages/cli` to use consistent wording by
rephrasing it to something like "`packages/cli` provides the CLI" (or similar
phrasing such as "contains the CLI interface") to satisfy the style warning
while preserving meaning; edit the `packages/cli` list entry in CONTRIBUTING.md
to use the new wording.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ee03e646-12c8-4430-9a31-c8967fd6fbd2

📥 Commits

Reviewing files that changed from the base of the PR and between 8efdbca and 6683773.

📒 Files selected for processing (5)
  • .claude/skills/changeset/SKILL.md
  • CONTRIBUTING.md
  • README.md
  • packages/cli/README.md
  • scripts/check-circular-deps.mjs
✅ Files skipped from review due to trivial changes (3)
  • packages/cli/README.md
  • scripts/check-circular-deps.mjs
  • .claude/skills/changeset/SKILL.md

@ericglau ericglau requested a review from pasevin March 27, 2026 21:29
Copy link
Copy Markdown

@pasevin pasevin left a comment

Choose a reason for hiding this comment

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

lgtm!

@ernestognw
Copy link
Copy Markdown
Member

ernestognw commented Mar 30, 2026

CodeRabbit pointed out this issue I think deserves attention:

packages/common/src/ai/schemas/schemas.test.ts (1)

42-70: Potential for both t.fail() and t.pass() to be called in nested schema validation.

When a nested ZodObject field fails validation in the recursive call (line 59), t.fail() is called and that recursive frame returns, but the outer loop continues via continue at line 60. If all remaining top-level fields pass, t.pass() at line 69 will also be called. Depending on AVA's behavior, this may mask failures or cause unexpected test outcomes.

Consider tracking failure state and returning early from the outer function:

♻️ Proposed fix
 function assertAllFieldsHaveDescriptions(
   t: { pass: () => void; fail: (msg: string) => void },
   shape: z.ZodRawShape,
   prefix = '',
-) {
+): boolean {
   for (const [key, schema] of Object.entries(shape)) {
     const zodSchema = schema as z.ZodTypeAny;
     const fullKey = prefix ? `${prefix}.${key}` : key;

     // Unwrap optional to check inner type
     let innerSchema = zodSchema;
     if (innerSchema._def.typeName === 'ZodOptional') {
       innerSchema = innerSchema._def.innerType as z.ZodTypeAny;
     }

     // For ZodObject fields, recurse into inner fields (the object itself may or may not have a description)
     if (innerSchema._def.typeName === 'ZodObject') {
-      assertAllFieldsHaveDescriptions(t, (innerSchema as z.ZodObject<z.ZodRawShape>).shape, fullKey);
-      continue;
+      if (!assertAllFieldsHaveDescriptions(t, (innerSchema as z.ZodObject<z.ZodRawShape>).shape, fullKey)) {
+        return false;
+      }
+      continue;
     }

     const desc = zodSchema.description ?? zodSchema._def?.innerType?.description;
     if (!desc) {
       t.fail(`Field "${fullKey}" is missing a .describe() string`);
-      return;
+      return false;
     }
   }
   t.pass();
+  return true;
 }
Details

Copy link
Copy Markdown
Member

@ernestognw ernestognw left a comment

Choose a reason for hiding this comment

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

LGTM aside from the CodeRabbit comment I pointed out

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 2, 2026

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 2, 2026

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

Ignoring alerts on:

  • @rollup/pluginutils@4.2.1
  • postcss-selector-parser@6.1.2
  • @changesets/changelog-github@0.5.1
  • @changesets/cli@2.29.5
  • @eslint/js@9.33.0
  • concurrently@9.2.0
  • eslint@9.33.0
  • @humanwhocodes/retry@0.4.3
  • eslint-config-prettier@10.1.8
  • eslint-plugin-prettier@5.5.4
  • eslint-plugin-unicorn@61.0.2
  • globals@16.3.0
  • prettier-plugin-svelte@3.4.0
  • typescript-eslint@8.39.1
  • @types/semver@7.7.1
  • @changesets/get-github-info@0.6.0
  • @changesets/types@6.1.0
  • dotenv@8.6.0
  • @changesets/apply-release-plan@7.0.12
  • @changesets/assemble-release-plan@6.0.9
  • @changesets/changelog-git@0.2.1
  • @changesets/config@3.1.1
  • @changesets/errors@0.2.0
  • @changesets/get-dependents-graph@2.1.3
  • @changesets/get-release-plan@4.0.13
  • @changesets/git@3.0.4
  • @changesets/logger@0.1.1
  • @changesets/pre@2.0.2
  • @changesets/read@0.6.5
  • @openzeppelin/contracts@5.4.0
  • @types/node@20.19.21
  • tslib@2.8.1
  • ajv@8.18.0
  • ci-info@3.9.0
  • glob-parent@6.0.2
  • iconv-lite@0.7.2
  • ignore@7.0.5
  • prettier@3.6.2
  • typescript@5.9.3

View full report

@ericglau
Copy link
Copy Markdown
Member Author

ericglau commented Apr 2, 2026

@SocketSecurity ignore-all
Looks like AI false positives

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants