Skip to content

feat(ai): add Jev decision model and two-stage comment moderation - #2826

Merged
Innei merged 3 commits into
masterfrom
feat/jev-comment-decision
Sep 23, 2026
Merged

Innei merged 3 commits into
masterfrom
feat/jev-comment-decision

Conversation

@Innei

@Innei Innei commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add a separate TypeSafe / Jev decision-model assignment in AI settings. Comments and replies receive synchronous decisions; uncertain, timed-out or unavailable decisions fall back to durable LLM review.
  • Keep moderation separate from read/unread state and human approval. Pending content stays private; receipt-protected status queries let the submitting frontend recover the result. Stale model results cannot override edits or manual actions.

Test plan

  • Comment regression suite: 19 files, 75 passed, 2 opt-in checks skipped; separately exercised live Jev and browser flows.
  • Decision adapter checks including native model listing: 5 passed; admin settings normalization: 24 passed.
  • Core typecheck, Core/Admin production builds, migration lint and isolated PostgreSQL migration application.
  • Browser verification of the actual settings component and Yohaku submission/status components with local Nest/PostgreSQL fixtures. External model and queue transports are mocked in the lifecycle/browser fixtures.
  • Six real Jev samples measured 343–939 ms; this is not a production P95 estimate.

Acceptance: https://app.lobehub.com/acceptance/4e4505eb-79d1-499b-86ec-ce3cba9901d8 (4/4 criteria, evidence uploaded).

Database migrations checklist

  • Full mixed-version rolling compatibility: not supported for comment traffic. Although migration 0040 only adds columns, old instances do not understand moderation state. Pause comment writes and drain old instances before restoring traffic on the new version. Follow docs/features/comment-decision-review.md; do not use an ordinary mixed-version rollout.
  • Additive schema only; no drop, rename or type change.
  • pnpm -C apps/core run lint:migrations passes; migration applied to isolated PostgreSQL databases.
  • No new indexes, lint exemptions or follow-up contract migration.

No production configuration or credentials are included. Deploy the backend before the corresponding Yohaku frontend.

Companion frontend: https://github.com/innei-dev/yohaku/pull/192

@safedep

safedep Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

SafeDep Report Summary

Green Malicious Packages Badge Green Vulnerable Packages Badge Green Risky License Badge

No dependency changes detected. Nothing to scan.

View complete scan results →

This report is generated by SafeDep GitHub App

Comment on lines +35 to +38
const endpoint = (provider.endpoint || 'https://api.typesafe.ai/v1').replace(
/\/+$/,
'',
)
Comment on lines +39 to +48
const response = await fetch(`${endpoint}/systemone`, {
method: 'POST',
headers: {
Authorization: `Bearer ${provider.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ model: provider.defaultModel, state, questions }),
signal,
redirect: 'error',
})
Comment on lines +85 to +88
const endpoint = (provider.endpoint || 'https://api.typesafe.ai/v1').replace(
/\/+$/,
'',
)
Comment on lines +89 to +93
const response = await fetch(`${endpoint}/models`, {
headers: { Authorization: `Bearer ${provider.apiKey}` },
signal: AbortSignal.timeout(10000),
redirect: 'error',
})

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e8cc8c45ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (
comment.moderationStatus === 'pending' ||
comment.moderationStatus === 'manual' ||
(requiresAudit && comment.state !== 1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep trusted reader submissions published

When commentShouldAudit is enabled, authenticated non-owner readers are passed to initialReview as trusted and receive moderationStatus: 'approved', but their state is still Unread. This condition therefore reports their submissions as pending and public queries hide them; because only moderationStatus: 'pending' rows are queued for review, these trusted comments remain hidden until an administrator manually changes their state, defeating the intended reader exemption.

Useful? React with 👍 / 👎.

Comment on lines +213 to +215
comment.isOwnerReply && published
? CommentReplyMailType.Guest
: CommentReplyMailType.Owner,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Notify the parent for authenticated reader replies

When a non-owner authenticated reader replies while auditing is disabled, isOwnerReply is false, so this selects CommentReplyMailType.Owner. The previous reply path selected Guest for every reply with a readerId, and sendEmail uses that type to address parentIdentity.mail; the new condition therefore sends the notification to the site owner instead of the person being replied to.

Useful? React with 👍 / 👎.

Comment on lines +284 to +286
...(type === 'typesafe'
? { endpoint: 'https://api.typesafe.ai/v1' }
: {}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset the endpoint when leaving TypeSafe

When an existing TypeSafe provider is changed to any text provider through this selector, the patch changes its type and model but leaves https://api.typesafe.ai/v1 in endpoint, because an endpoint is only assigned when entering TypeSafe. Model fetching and connection tests then send the new provider protocol to the TypeSafe API and fail until the user notices and manually replaces the stale endpoint.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-23T11:25:17.978979Z f3628a2 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Map track JSON gains optional segments and a legs index over them; the
map node schema is unchanged. The insert dialog accepts multiple GPX
files with per-leg title, order and removal, and the preview draws
disconnected segments without bridging gaps.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd44f1b817

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +405 to +409
moderationStatus === 'rejected'
? CommentState.Junk
: RequestContext.hasAdminAccess()
? CommentState.Read
: CommentState.Unread,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep pending comments hidden during rolling deploys

During the normal two-replica rolling deployment, a new replica can insert a low-confidence or failed review with moderationStatus: 'pending', but this branch still assigns the legacy Unread state. An old replica's public thread query accepts both unread and read rows when commentShouldAudit is disabled and does not inspect moderation_status, so it can expose the pending comment until the old replica is drained. Preserve a legacy-hidden state or gate these writes until every instance is upgraded rather than relying on a manual traffic pause.

AGENTS.md reference: AGENTS.md:L87-L89

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

const closeDetail = useCallback(() => {
navigate(buildListUrl())
}, [buildListUrl, navigate])
const selectedTargetsRef = useRef<CommentModel[]>([])

P1 Badge Do not publish audit-gated comments when opening them

When commentShouldAudit is enabled, an anonymous comment that passes the model has moderationStatus: 'approved' but remains pending until its Unread state is explicitly approved. This condition still invokes markReadOnOpenMutation for that row; the repository translates the resulting Read state into an approved, publicly visible comment. Consequently, merely opening a comment that requires human review publishes it, contrary to the intended manual-approval flow.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Innei
Innei merged commit 77225ab into master Sep 23, 2026
13 of 14 checks passed
@Innei
Innei deleted the feat/jev-comment-decision branch September 25, 2026 18:32
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.

2 participants