-
Notifications
You must be signed in to change notification settings - Fork 51
ci: integrate UCI AI review, AI assistant, and stale check #317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| name: AI Assistant | ||
| on: | ||
| issue_comment: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Two consequences worth a caller-side guard:
The if: >-
github.event.sender.type != 'Bot' &&
contains(github.event.comment.body || github.event.review.body, '@seidroid')A |
||
| types: [ created ] | ||
| pull_request_review_comment: | ||
| types: [ created ] | ||
| pull_request_review: | ||
| types: [ submitted ] | ||
| jobs: | ||
| assistant: | ||
| # See: https://github.com/sei-protocol/uci/releases/tag/v0.0.15 | ||
| uses: sei-protocol/uci/.github/workflows/ai-assistant.yml@65901242783550521f25a19199a6b10e54550b97 | ||
| permissions: | ||
| contents: read | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] Worth confirming |
||
| pull-requests: write | ||
| issues: write | ||
| id-token: write | ||
| secrets: inherit | ||
| with: | ||
| # See: https://github.com/sei-protocol/uci/releases/tag/v0.0.15 | ||
| uci-ref: 65901242783550521f25a19199a6b10e54550b97 | ||
| allowed-team: 'sei-protocol/sei-core' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| name: AI Review | ||
| on: | ||
| pull_request: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Because this uses To be clear: staying on |
||
| # `labeled`/`unlabeled` let the `ai: skip-review` label take effect immediately rather | ||
| # than on the next push. UCI ignores those two events for every other label. | ||
| types: [ opened, ready_for_review, synchronize, reopened, labeled, unlabeled ] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] No Unless UCI's concurrency:
group: ai-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] No With concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: trueSeparately, worth being aware that |
||
| jobs: | ||
| ai-review: | ||
| # See: https://github.com/sei-protocol/uci/releases/tag/v0.0.15 | ||
| uses: sei-protocol/uci/.github/workflows/ai-review.yml@65901242783550521f25a19199a6b10e54550b97 | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| checks: write | ||
| id-token: write | ||
| secrets: inherit | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] The SHA pin and same-org ownership make this acceptable, so this is hygiene rather than a vulnerability — but enumerating just the required secrets under |
||
| with: | ||
| # See: https://github.com/sei-protocol/uci/releases/tag/v0.0.15 | ||
| uci-ref: 65901242783550521f25a19199a6b10e54550b97 | ||
| enable-cursor: false # Disabled for now since there is a dedicated Bugbot flow built into Cursor currently enabled on repo. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| name: UCI | ||
| run-name: UCI / Stale Check | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| schedule: | ||
| - cron: '0 12 * * *' | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.sha }} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] Keying concurrency on
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] Keying the concurrency group on |
||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| stale: | ||
| name: Stale | ||
| # Job-level `permissions` replaces the workflow-level block rather than merging, | ||
| # so `contents: read` has to be repeated here to survive. | ||
| permissions: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Job-level Both sibling workflows added in this PR explicitly include Suggest adding |
||
| contents: read | ||
| issues: write | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] This job is granted Since this runs unattended every day at 12:00 UTC and can comment on or close issues, the issue-side behaviour should be explicit rather than inherited: either pass |
||
| pull-requests: write | ||
| # See: https://github.com/sei-protocol/uci/releases/tag/v0.0.15 | ||
| uses: sei-protocol/uci/.github/workflows/stale-check.yml@65901242783550521f25a19199a6b10e54550b97 | ||
| with: | ||
| days-before-pr-stale: 28 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| # Review guidelines for AI agents | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [blocker] The filename looks wrong, which would make this whole file dead weight. The PR description says this "is the guidelines file UCI's reviewer loads from the PR base branch" — but the reviewer harness that ran on this PR was handed a base-branch file named Worth checking directly against (If v0.0.15 genuinely reads |
||
|
|
||
| Repo-specific conventions for automated PR review (Codex, Cursor, Claude, and | ||
| any other AI reviewer). This is a pnpm workspace that publishes six | ||
| independently versioned `@sei-js/*` packages to npm, so a defect ships to every | ||
| downstream dApp that upgrades rather than to a single deployment we control. | ||
| Calibrate accordingly: a wrong precompile address or a weakened wallet guard is | ||
| far more valuable to catch than a style nit, and several patterns below look | ||
| like bugs in isolation but are deliberate. | ||
|
|
||
| ## 1. `packages/mcp-server` is the security surface | ||
|
|
||
| This package hands blockchain capabilities to an LLM client, so it is the one | ||
| place in the repo where a subtle regression can cost users funds. Two | ||
| invariants are load-bearing and are enforced in code rather than by convention: | ||
|
|
||
| - **Wallet mode is stdio-only.** `validateSecurityConfig()` in | ||
| `src/server/transport/security.ts` halts the process when the wallet is | ||
| enabled and the transport is `streamable-http` or `http-sse`. HTTP | ||
| transports are reachable cross-origin, so a signing key behind one is a | ||
| drain-the-wallet primitive. Any change that narrows this check, makes it | ||
| non-fatal, or adds a transport that bypasses it is a finding. | ||
| - **SSE messages are bound to their session.** | ||
| `src/server/transport/http-sse.ts` keys `connections` by | ||
| `transport.sessionId` and requires a matching `?sessionId=` on | ||
| `POST {path}/message` (400 when absent, 404 when unknown). This replaced an | ||
| implementation that routed to the first connection in the map, which let one | ||
| client inject into another's stream. Treat any reintroduction of positional | ||
| or implicit session lookup as a regression, and keep the isolation tests in | ||
| `src/tests/server/transport/http-sse.test.ts` meaningful. | ||
|
|
||
| Beyond those, scrutinise anything that widens what a caller controls: contract | ||
| ABIs reach `JSON.parse` from tool arguments in `src/core/tools.ts`, addresses | ||
| and call arguments arrive unvalidated from the model, and RPC endpoints are | ||
| overridable through `MAINNET_RPC_URL` / `TESTNET_RPC_URL` / `DEVNET_RPC_URL` in | ||
| `src/core/chains.ts`. Private keys are read from the environment in | ||
| `src/core/config.ts` and must never reach a log line, an error message, or a | ||
| tool response. | ||
|
|
||
| Note that `.github/workflows/pr-to-slack-codex.yml` already runs a separate | ||
| AppSec pass to Slack. Overlapping findings are expected; don't suppress a real | ||
| issue because you assume the other reviewer caught it. | ||
|
|
||
| ## 2. Precompile addresses and ABIs are hand-maintained source | ||
|
|
||
| `packages/precompiles/src/precompiles/*.ts` is not generated — there is no | ||
| codegen step or ABI pipeline in this repo. An address or ABI entry changed | ||
| there is a change to the source of truth, and a wrong value silently misroutes | ||
| every consumer's calls. You usually cannot settle these from the diff alone, so | ||
| when a value looks suspect, ask for the authoritative source rather than | ||
| asserting it is wrong: link what you checked (`docs.sei.io`, `sei-chain`, | ||
| Seiscan) and say what disagrees. An unsourced change to an existing documented | ||
| address, chain ID, or ABI signature is worth raising on its own. | ||
|
|
||
| ## 3. A publishable change needs a changeset | ||
|
|
||
| `.changeset/config.json` sets `fixed: []` and `linked: []`, so every package | ||
| versions independently — do not expect or request a coordinated bump. Merging | ||
| to `main` opens a "Version Packages" PR, and merging that publishes. A | ||
| user-facing change to a published package with no `.changeset/*.md` file ships | ||
| the code without releasing it, which is the common miss on this repo. | ||
|
|
||
| Ask for a changeset when a published package's behaviour, types, or | ||
| dependencies change. Docs-only, CI-only, and changes confined to | ||
| `packages/create-sei/templates/**` generally don't need one, though the repo | ||
| has deliberately added patch changesets across all six packages for | ||
| release-note visibility (the `@asyncapi` pinning in `pnpm.overrides` is the | ||
| precedent). Absence of a changeset on that kind of PR is a question, not a | ||
| defect. | ||
|
|
||
| ## 4. Known non-issues — do not flag these | ||
|
|
||
| - **`console.error` used for informational messages.** Under the stdio | ||
| transport, stdout carries the JSON-RPC frames, so anything written there | ||
| corrupts the protocol. `console.error('MCP Server ready (stdio transport)')` | ||
| in `src/server/transport/stdio.ts` is correct. Never suggest converting | ||
| these to `console.log`. The inverse *is* a finding: a new `console.log` on a | ||
| path reachable from stdio breaks the transport. | ||
| - **The CORS middleware sets no `Access-Control-Allow-Origin`.** | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] This entry is accurate about browsers but risks suppressing a real gap. "Deny-by-default" only holds for browser clients that honour the missing The wallet guard in |
||
| `createCorsMiddleware()` answers preflights with a bare 204 and no CORS | ||
| headers. That is deny-by-default: a browser treats the missing header as a | ||
| failure and blocks the request. It is not an oversight and not a permissive | ||
| wildcard. | ||
| - **`process.exit(1)` inside `validateSecurityConfig()`.** Failing closed at | ||
| startup is the intent. Do not ask for a thrown error the caller might swallow. | ||
| - **`packages/registry/chain-registry` and `.../community-assetlist` are | ||
| missing from the tree.** Both are git submodules (`.gitmodules`) and are | ||
| listed in `.gitignore`; they are populated by the `registry` package's | ||
| `postinstall` and by CI's submodule checkout. Their JSON is vendored | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] "and by CI's submodule checkout" is only half true: |
||
| upstream — review the TypeScript wrappers, not the data. | ||
| - **Biome findings are not enforced anywhere.** `biome.json` configures tabs, | ||
| 160-column lines, single quotes and no trailing commas, but no package | ||
| defines a `biome` script and `.github/workflows/checks.yml` runs only | ||
| `pnpm build:all` and `pnpm test:all`. Match the surrounding style; do not | ||
| file formatting-only findings as blocking. | ||
| - **Test file naming is inconsistent across packages.** `mcp-server` and | ||
| `create-sei` use `*.test.ts`; `precompiles`, `ledger`, `registry` and | ||
| `sei-global-wallet` use `*.spec.ts` under `__tests__/`. Follow the | ||
| convention of the package being changed rather than proposing a repo-wide | ||
| rename. | ||
| - **`mcp-server` has no Codecov target.** `codecov.yml` defines 80% project | ||
| targets for the other five packages only. Thin coverage on an mcp-server PR | ||
| is worth mentioning on its merits, but it does not fail a gate. | ||
| - **`noImplicitAny: false` in `tsconfig.base.json`.** This is a deliberate | ||
| repo-wide setting. Flag an untyped value when it actually causes an unsound | ||
| path, not because the compiler permitted it. | ||
| - **The `create-sei` templates are excluded from the root Biome config** and | ||
| carry their own toolchain. Do not apply root formatting rules to anything | ||
| under `packages/create-sei/templates/`. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit]
issue_commentfires for comments on issues as well as PRs, from any user on a public repo, so every drive-by comment anywhere in the repo spawns a workflow run. Gating rests entirely on UCI'sallowed-teamcheck (line 22).Delegating the authorization check to the reusable workflow is a reasonable design, but worth verifying two things at the pinned SHA: that the team check runs before any comment body reaches the agent as instructions, and that a non-member comment exits cleanly rather than as a failed run.