Skip to content

chore: add typecheck, lint, and CI gates for AI-assisted development#16

Merged
moyunzero merged 3 commits into
masterfrom
chore/dev-quality-gates
Jun 28, 2026
Merged

chore: add typecheck, lint, and CI gates for AI-assisted development#16
moyunzero merged 3 commits into
masterfrom
chore/dev-quality-gates

Conversation

@moyunzero

@moyunzero moyunzero commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add bun run check (typecheck + Biome lint + test) as the repo-wide verification contract and document it in AGENTS.md with package boundaries and Definition of Done.
  • Introduce Biome (lint only, formatter off), clear the lint/typecheck baseline on production sources, and fix related type issues in chat/stream code.
  • Add GitHub Actions CI that blocks merge unless typecheck, lint, and test all pass.

Test plan

  • bun run typecheck — 0 errors
  • bun run lint — 0 errors
  • bun run test — 215 pass / 0 fail
  • bun run check — exit 0
  • CI workflow green on this PR

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added automated checks on pushes and pull requests to validate code quality before merge.
    • Introduced project-wide commands for running type checks, linting, and tests together.
  • Bug Fixes

    • Improved stability in chat/session flows and message rendering.
    • Made resume and interrupt handling more defensive around missing or incomplete data.
    • Refined polling, scrolling, and dialog behavior for smoother interactions.

Establish bun run check (typecheck + biome lint + test) as the verification
contract in AGENTS.md, fix the resulting type/lint baseline, and wire GitHub
Actions so merges require all three gates to pass.

Co-authored-by: Cursor <cursoragent@cursor.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@railway-app railway-app Bot temporarily deployed to lavish-courage / MoCode-TUI-pr-16 June 28, 2026 12:11 Destroyed
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@moyunzero, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 33 minutes and 49 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b28f4264-a597-4d32-841f-5cb906d87b1a

📥 Commits

Reviewing files that changed from the base of the PR and between c2c263e and d7bebb1.

📒 Files selected for processing (11)
  • .github/workflows/ci.yml
  • packages/cli/src/components/messages/bot-message.tsx
  • packages/cli/src/lib/bot-message-parts.test.ts
  • packages/cli/src/lib/bot-message-parts.ts
  • packages/cli/src/lib/hydrate-message-parts.ts
  • packages/cli/src/lib/stream-interrupt-resume.test.ts
  • packages/cli/src/lib/stream-interrupt.ts
  • packages/cli/src/screens/session.tsx
  • packages/cli/src/utils/list-scroll-nav.test.ts
  • packages/cli/src/utils/list-scroll-nav.ts
  • packages/cli/tsconfig.json
📝 Walkthrough

Walkthrough

Adds a GitHub Actions CI workflow with Bun-based typecheck, lint, and test gates, plus Biome linter configuration and root-level scripts. Accompanies these with targeted TypeScript type-safety fixes (SupportedChatModelId propagation, as never casts, undefined guards), React hook dependency array corrections, stable render keys in BotMessage, and minor unused-variable removals across CLI and server packages.

Changes

CI Tooling, Type Safety, and Hook Fixes

Layer / File(s) Summary
CI workflow, Biome config, scripts, and contributor docs
.github/workflows/ci.yml, biome.json, package.json, AGENTS.md, packages/cli/tsconfig.json, packages/server/tsconfig.json, packages/shared/tsconfig.json
Adds CI workflow triggered on main pushes and PRs; adds Biome linter config targeting packages/**/src/**/*.ts|tsx; adds typecheck, lint, test, check scripts to root package.json; adds contributor gates and package boundary rules to AGENTS.md; updates all tsconfigs to exclude **/*.test.ts.
TypeScript type-safety fixes across transport, interrupt, and MCP tools
packages/cli/src/lib/local-chat-transport.ts, packages/cli/src/lib/local-chat-transport.test.ts, packages/cli/src/lib/stream-interrupt.ts, packages/server/src/lib/stream-interrupt.ts, packages/cli/src/lib/mcp-tool-call.ts, packages/cli/src/mcp/tools.ts, packages/shared/src/mcp-tools.ts, packages/cli/src/hooks/use-chat.ts, packages/cli/package.json
Introduces LocalChatMetadata type and findLastMetadataValue helpers in LocalChatTransport; propagates SupportedChatModelId through resolveAutoResumeRequest and stream-interrupt; adds undefined guards in finalizeInterruptedAssistant (both CLI and server); applies as never type casts to dynamicTool assignments; adds McpToolConfigOverride type to mcp-tool-call; explicitly casts LocalChatTransport to ChatTransport<Message>.
React hook dependency fixes and render key corrections
packages/cli/src/hooks/use-chat.ts, packages/cli/src/screens/session.tsx, packages/cli/src/components/input-bar.tsx, packages/cli/src/components/dialogs/mcp-dialog.tsx, packages/cli/src/providers/dialog/index.tsx, packages/cli/src/components/command-menu/use-command-menu.ts, packages/cli/src/components/messages/bot-message.tsx
Removes chat.status/chat.error from effect dependency arrays in use-chat; narrows scroll useLayoutEffect deps to isLoading; makes abort cleanup run once; adds composerRestore via useMemo in input-bar; removes busyServers from MCP dialog effect deps; adds push to dialog close callback deps; removes setResponder from command-menu destructuring; switches BotMessage render keys from index to group.key + part.text.
Minor cleanup and server stream fixes
packages/server/src/routes/chat.ts, packages/server/src/system-prompt.test.ts, packages/cli/src/providers/keyboard-layer/index.tsx, packages/cli/src/providers/theme/index.tsx, packages/cli/src/providers/toast/index.tsx, packages/cli/src/screens/new-session.tsx
Server SSE replay now pipes through TextEncoderStream; hasPendingToolCalls passed via inline cast wrapper; system-prompt test regex updated; keyboard-layer uses responder?.() optional chaining; catch(error)catch {}; removes unused height and Mode imports.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • moyunzero/MoCode-TUI#14: Shares direct code overlap in local-chat-transport.ts, mcp-tool-call.ts, stream-interrupt.ts, mcp/tools.ts, and server/routes/chat.ts — this PR makes type-safety edits to the same functions.
  • moyunzero/MoCode-TUI#15: Core stream-interrupt/resume implementation in finalizeInterruptedAssistant, detectResumeEligibility, and resolveAutoResumeRequest — this PR adds undefined guards and type narrowing to those same functions.

Poem

🐇 Hop, hop — the CI gate is set!
Biome lints what typecheck won't forget,
No as any shall slip through my paws,
Each hook dep trimmed without a pause.
The tests all green, the bunny grins wide —
Clean code merged with cottontail pride! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding typecheck, lint, and CI gates plus supporting verification updates.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/dev-quality-gates

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

❤️ Share

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

CI bun install runs server postinstall (prisma generate), which requires
DATABASE_URL to be defined even though no live database is needed.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Caution

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

⚠️ Outside diff range comments (1)
packages/cli/src/components/input-bar.tsx (1)

343-351: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Cursor moves no longer resync the mention menu.

syncMentionMenu now only runs on content edits. If the user moves the caret with arrows or mouse, the @mention popup can stay open or point at the wrong token until the next text change. Please keep a cursor-change sync path alongside onContentChange.

Also applies to: 615-623

🤖 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 `@packages/cli/src/components/input-bar.tsx` around lines 343 - 351, The
mention menu only syncs from content edits in handleTextareaContentChange, so
cursor-only moves can leave the `@mention` popup stale. Add a separate
cursor-change sync path in input-bar.tsx that also calls syncMentionMenu when
the caret moves, and wire it through the textarea event handling alongside
onContentChange (using the existing textareaRef, handleContentChange, and
syncMentionMenu helpers) so mouse/arrow navigation keeps the menu aligned.
🧹 Nitpick comments (2)
packages/cli/src/hooks/use-chat.ts (1)

468-468: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Keep continueGeneration keyed to the members it actually uses.

Line 468’s [chat] dependency will recreate this callback whenever useAiChat() returns a fresh object, which then churns downstream consumers like SessionChat’s auto-resume effect and session-actions memo. Prefer the specific chat.* members read inside the callback instead of the whole object.

🤖 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 `@packages/cli/src/hooks/use-chat.ts` at line 468, The `continueGeneration`
callback in `use-chat.ts` is over-dependent on the full `chat` object, which
causes unnecessary recreation when `useAiChat()` returns a new reference. Update
the dependency list to include only the specific `chat.*` members actually read
inside `continueGeneration` so the callback stays stable and avoids downstream
churn in `SessionChat` and related memoized actions.
packages/cli/src/mcp/tools.ts (1)

72-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid casting the whole dynamicTool() config to never.
This hides the schema/type mismatch at the call site; narrow the cast to inputSchema or give jsonSchemaToInputSchema() an explicit SDK schema return type. The same pattern also exists in packages/shared/src/mcp-tools.ts.

🤖 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 `@packages/cli/src/mcp/tools.ts` around lines 72 - 75, The `dynamicTool()`
setup is masking a type mismatch by casting the entire config to `never`, which
should be fixed at the source. Update the `buildMcpTools`/`dynamicTool` call to
use a properly typed `inputSchema` value instead of casting the whole object,
either by narrowing the cast to `jsonSchemaToInputSchema(tool.inputSchema)` or
by giving `jsonSchemaToInputSchema()` an explicit SDK schema return type. Apply
the same correction in `packages/shared/src/mcp-tools.ts` where the same pattern
appears.
🤖 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 @.github/workflows/ci.yml:
- Around line 3-19: The CI workflow currently checks out PR code and runs it
with overly broad default token access; harden the job by reducing the
permissions granted to the built-in token and preventing the checkout token from
being persisted. Update the check job in the workflow to explicitly set minimal
`permissions` and configure the `actions/checkout@v4` step so the token is not
left available to later PR-controlled steps, while keeping the existing
`setup-bun` and install flow intact.
- Around line 14-16: The CI workflow is using a floating Bun version, which
makes builds non-reproducible. Update the setup-bun step to pin Bun to an exact
version instead of using bun-version: latest, or read the version from a
checked-in version file so the workflow stays stable; locate the change in the
setup-bun@v2 configuration.

In `@packages/cli/src/components/messages/bot-message.tsx`:
- Around line 142-146: The key for reasoning parts in the bot-message rendering
is not stable when identical text repeats within the same grouped batch. Update
the map in bot-message.tsx inside the group.parts render logic to use a stable
disambiguator such as the inner part index or a per-part id instead of part.text
in the key for the reasoning branch, so repeated reasoning/text chunks do not
collide.

In `@packages/cli/src/lib/stream-interrupt.ts`:
- Around line 134-143: The resume metadata path is still persisting `model` as
an unvalidated string in `trimMessagesForRegenerate`, while
`resolveAutoResumeRequest` later trusts it as `SupportedChatModelId`. Update the
write path to store only a `SupportedChatModelId` for `params.model`, or add a
validation step before reading `lastUser.metadata.model` in
`resolveAutoResumeRequest` so unsupported/stale values are rejected. Use the
existing `trimMessagesForRegenerate` and `resolveAutoResumeRequest` symbols to
keep the persisted model aligned with the resume contract.

In `@packages/cli/tsconfig.json`:
- Line 8: The typecheck gate is excluding a production module, which lets
shipped code bypass validation. Update the packages/cli tsconfig so only test
files are excluded, and fix any typing issues in
src/lib/hydrate-message-parts.ts instead of carving it out; use the existing
typecheck setup and the hydrate-message-parts module as the place to resolve
errors.

---

Outside diff comments:
In `@packages/cli/src/components/input-bar.tsx`:
- Around line 343-351: The mention menu only syncs from content edits in
handleTextareaContentChange, so cursor-only moves can leave the `@mention` popup
stale. Add a separate cursor-change sync path in input-bar.tsx that also calls
syncMentionMenu when the caret moves, and wire it through the textarea event
handling alongside onContentChange (using the existing textareaRef,
handleContentChange, and syncMentionMenu helpers) so mouse/arrow navigation
keeps the menu aligned.

---

Nitpick comments:
In `@packages/cli/src/hooks/use-chat.ts`:
- Line 468: The `continueGeneration` callback in `use-chat.ts` is over-dependent
on the full `chat` object, which causes unnecessary recreation when
`useAiChat()` returns a new reference. Update the dependency list to include
only the specific `chat.*` members actually read inside `continueGeneration` so
the callback stays stable and avoids downstream churn in `SessionChat` and
related memoized actions.

In `@packages/cli/src/mcp/tools.ts`:
- Around line 72-75: The `dynamicTool()` setup is masking a type mismatch by
casting the entire config to `never`, which should be fixed at the source.
Update the `buildMcpTools`/`dynamicTool` call to use a properly typed
`inputSchema` value instead of casting the whole object, either by narrowing the
cast to `jsonSchemaToInputSchema(tool.inputSchema)` or by giving
`jsonSchemaToInputSchema()` an explicit SDK schema return type. Apply the same
correction in `packages/shared/src/mcp-tools.ts` where the same pattern appears.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7407aa22-057e-4a9d-a4b2-7fabe5803c18

📥 Commits

Reviewing files that changed from the base of the PR and between 42e753a and c2c263e.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (28)
  • .github/workflows/ci.yml
  • AGENTS.md
  • biome.json
  • package.json
  • packages/cli/package.json
  • packages/cli/src/components/command-menu/use-command-menu.ts
  • packages/cli/src/components/dialogs/mcp-dialog.tsx
  • packages/cli/src/components/input-bar.tsx
  • packages/cli/src/components/messages/bot-message.tsx
  • packages/cli/src/hooks/use-chat.ts
  • packages/cli/src/lib/local-chat-transport.test.ts
  • packages/cli/src/lib/local-chat-transport.ts
  • packages/cli/src/lib/mcp-tool-call.ts
  • packages/cli/src/lib/stream-interrupt.ts
  • packages/cli/src/mcp/tools.ts
  • packages/cli/src/providers/dialog/index.tsx
  • packages/cli/src/providers/keyboard-layer/index.tsx
  • packages/cli/src/providers/theme/index.tsx
  • packages/cli/src/providers/toast/index.tsx
  • packages/cli/src/screens/new-session.tsx
  • packages/cli/src/screens/session.tsx
  • packages/cli/tsconfig.json
  • packages/server/src/lib/stream-interrupt.ts
  • packages/server/src/routes/chat.ts
  • packages/server/src/system-prompt.test.ts
  • packages/server/tsconfig.json
  • packages/shared/src/mcp-tools.ts
  • packages/shared/tsconfig.json

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/ci.yml Outdated
Comment thread packages/cli/src/components/messages/bot-message.tsx Outdated
Comment thread packages/cli/src/lib/stream-interrupt.ts
Comment thread packages/cli/tsconfig.json Outdated
@railway-app

railway-app Bot commented Jun 28, 2026

Copy link
Copy Markdown

🚅 Deployed to the MoCode-TUI-pr-16 environment in lavish-courage

Service Status Web Updated (UTC)
@mocode/server ✅ Success (View Logs) Web Jun 28, 2026 at 12:11 pm

Harden CI (master trigger, pinned Bun, minimal permissions), remove dead
hydrate-message-parts, validate resume model ids, fix streaming scroll and
bot-message keys, with unit tests for each.

Co-authored-by: Cursor <cursoragent@cursor.com>
@moyunzero moyunzero merged commit f85fe23 into master Jun 28, 2026
3 checks passed
@railway-app railway-app Bot temporarily deployed to lavish-courage / MoCode-TUI-pr-16 June 28, 2026 12:41 Destroyed
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.

1 participant