Files
civitai__civitai/.gitignore
T
Manuel Emilio Urena 0ddd82b64a fix(challenge): escalate NSFW-text challenges — cancel green, raise R on yellow (#3211)
* docs(challenge): spec for NSFW text-scan escalation + green→yellow flip

Design for escalating a user challenge to R and flipping green→yellow when its
text scans as sexual content, plus currency-scoping the initial-prize
externalTransactionId to prevent a silent-drop unfunded-pool bug on re-charge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(challenge): implementation plan for NSFW scan escalation + flip

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(challenge): currency-scope initial-prize externalTransactionId

Refunding a charge leaves its externalTransactionId occupied in the ledger, so a
later yellow re-charge on the shared green id would be silently dropped by the
createBuzzTransaction dedup, leaving an unfunded pool. Suffix the id with the
currency; the -creator prefix matchers still match both variants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(challenge): scan text for suggestive+explicit, not nsfw only

The nsfw label (threshold 0.75) misses crude sexual themes; suggestive/explicit
(threshold 0.5) catch them with a large margin. Centralize the label set so the
adapter submit and scanUserChallenge stay in sync.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(challenge): add computeNsfwEscalation pure decision

Given a scanned challenge, decides the raised allowed/display nsfw levels and
whether a green user challenge flips to yellow + refunds its green initial prize.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(challenge): applyChallengeNsfwEscalation IO helper

Applies a scan verdict: marks Scanned, raises to R, flips green->yellow, refunds
the green initial prize (refund-before-update for crash safety), updates the
collection browsing level, and notifies the creator. Idempotent on retry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(challenge): delegate scan applyResult to escalation helper

The adapter now keeps only the Blocked path; clean/NSFW verdicts route through
applyChallengeNsfwEscalation, treating any triggered label as NSFW.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(challenge): broaden flip refund prefix + harden collection update

- Flip refund uses the -creator prefix so it also matches pre-deploy charge
  ids (-creator, no currency suffix); the narrow -creator-green prefix missed
  them and stranded the creator's escrow while zeroing the pool.
- collection.updateMany instead of update so a deleted collection no-ops
  rather than poison-pilling webhook retries with P2025.
- Refresh the adapter's stale top-of-file comment for the delegated flip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(challenge): pivot design from green→yellow flip to cancel/void

Cancelling a green NSFW challenge (via the existing race-safe voidChallenge)
instead of flipping it to yellow reuses battle-tested code and eliminates the
currency-migration edge cases. Yellow challenges still raise to R.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(challenge): cancel green NSFW challenges instead of flipping to yellow

Green user challenges whose text scans NSFW are now voided (Cancelled +
collection closed + initial prize refunded via the race-safe voidChallenge)
and the creator is notified to recreate on civitai.red. Yellow challenges still
raise to R and stay live. Replaces the buzzType-flip + green-prize-refund path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs+test(challenge): refresh adapter comment for cancel; add already-R escalation case

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(challenge): correct cancel-path ordering to void-before-Scanned

Match the spec to the implemented (crash-safe) order: void first so a crash
leaves the challenge Cancelled/hidden, never Scanned-and-visible.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(challenge): guard blocked-path against deleted challenge + align stale docs

- adapter blocked path: early-return when the challenge was deleted between
  scan submit and the webhook, instead of a bare update that throws P2025 and
  fails the moderation callback (restores pre-refactor behavior).
- spec title + plan header: flag the flip→cancel pivot so the docs don't read
  as though the code is wrong.

Addresses Copilot PR review feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(challenge): scan nsfw label only (suggestive/explicit not yet reliable)

Only the nsfw XGuard label is currently trustworthy, so scan for it alone.
Trade-off: nsfw's 0.75 threshold misses borderline sexual text (~0.68) — only
clearly-NSFW text escalates until suggestive/explicit are reliable. Escalation
logic is label-agnostic; this is a one-const change.

* docs(challenge): document text-scan NSFW handling in feature doc; drop session spec/plan

Add a Text moderation bullet to the challenge-platform Safety/gating section
(green NSFW → void+refund, yellow → raise to R, nsfw-label-only interim). Remove
the superpowers/ spec + plan — implementation scratch that doesn't belong in main.

* docs: remove superpowers/specs scratch (article-rating #2779, public-challenges #2965)

Implementation-detail specs that don't belong in main; removed per maintainer
request alongside this PR's own doc cleanup.

* chore: gitignore docs/superpowers/ (skill scratch, not shipped to main)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 15:13:04 -04:00

165 lines
2.6 KiB
Plaintext

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
node_modules
/.pnp
.pnp.js
# testing
coverage/
# database
/prisma/db.sqlite
/prisma/db.sqlite-journal
# Generated slim schema - edit schema.full.prisma instead
prisma/schema.prisma
packages/civitai-db-schema/prisma/schema.prisma
# next.js
/.next/
/out/
# Auto-generated by `next dev`/`next build`; its import path flips between
# .next/dev/types and .next/types depending on the last command run, so
# tracking it just creates churn. Next regenerates it on every run.
next-env.d.ts
# ladle
.ladle/stubs/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env
.env*
!.env-example
!.env.example
# vercel
.vercel
# typescript
*.tsbuildinfo
# docker volumes
/postgres*
/redis
/minio
# browser automation (local session/profile data)
.browser/sessions/
.browser/profiles/
.browser/storage/
/clickhouse*
/undefined
/.docker
/prisma_pit
# Meilisearch
/meilisearch
/data.ms/
# WebStorm
.idea
*.http
# SEO
/public/sitemap*.xml
/public/robots.txt
ca-certificate.crt
# IDE
*~
src/pages/api/admin/*.json
trace/trace.json
trace/types.json
# Local files
/src/local
.todo
/analyze
# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/tests/auth/*.json
src/pages/api/dev-local/*
/.playwright-mcp/
# Vitest browser-mode failure screenshots (written next to *.browser.test.tsx)
**/__screenshots__/
# Ladle (local dev artifacts)
.ladle/stubs/
# LLM
/.serena/
docs/working/
docs/incidents/
.claude/*.local.*
.claude/skills/cloudflare/.port-tmp-path
local/
.eslintcache
nul
scripts/local-dev/
.direnv
# Claude agent temp directories
tmpclaude-*-cwd
.claude/skills/flipt/.env
.claude/skills/freshdesk/.env
# Ralph agent
scripts/ralph/prd.json
scripts/ralph/progress.txt
# Claude temp files
tmpclaude-*
/.claude/worktrees
.claude/scheduled_tasks.lock
# Bundled SharedWorker scripts (generated by pnpm build:workers)
/public/workers/
# nested Next build output (apps/*)
apps/*/.next/
# nested SvelteKit generated output (apps/*)
apps/*/.svelte-kit/
# Turborepo local task cache
.turbo/
# Lighthouse CI — runtime config (cookie-injected) + report output, never committed
lighthouserc.runtime.json
.lighthouseci/
# Playwright hub e2e generated artifacts
apps/auth/e2e/playwright-report/
apps/auth/e2e/test-results/
apps/auth/e2e/.auth/
mockups/
# local-only SQL (never committed)
*.local.sql
*.local.md
# superpowers skill scratch (specs/plans) — implementation detail, not shipped to main
docs/superpowers/