mirror of
https://github.com/civitai/civitai.git
synced 2026-09-20 22:08:18 +08:00
Merge branch 'main' into feat/training-studio-app
This commit is contained in:
@@ -6,14 +6,14 @@ All controllers/nodes rendered inside the `<AccordionLayout label="Advanced">` s
|
||||
|---|-----------|-------|-----------------|-------------|-------------|
|
||||
| 1 | `cfgScale` | CFG Scale | `SliderInput` | Controls how closely generation follows the text prompt | — |
|
||||
| 2 | `sampler` | Sampler | `SelectInput` | Sampling method — each produces different results | — |
|
||||
| 3 | `scheduler` | Scheduler | `SelectInput` | Controls the noise schedule during generation | SdCpp ecosystems |
|
||||
| 3 | `scheduler` | Scheduler | `SelectInput` | Controls the noise schedule during generation | Anima, Flux2Klein, ZImage |
|
||||
| 4 | `steps` | Steps | `SliderInput` | Number of iterations spent generating | — |
|
||||
| 5 | `movementAmplitude` | Movement Amplitude | `SegmentedControlWrapper` | Camera movement and subject action scale | Vidu |
|
||||
| 6 | `seed` | Seed | `SeedInput` | Random seed for reproducibility | — |
|
||||
| 7 | `clipSkip` | CLIP Skip | `SliderInput` | Skip CLIP layers | SD only |
|
||||
| 8 | `denoise` | Denoise Strength | `SliderInput` | Denoising strength for img2img | img2img only (renders `null` when no meta) |
|
||||
| 9 | `vae` | VAE | `ResourceSelectInput` | Additional color and detail improvements | SD only |
|
||||
| 10 | `enhancedCompatibility` | Enhanced Compatibility | `Checkbox` | Toggle enhanced compatibility mode | — |
|
||||
| 10 | `enhancedCompatibility` | Enhanced Compatibility | `Checkbox` | Off (default) runs sdcpp; on runs comfyui | SD1, SDXL — txt2img only |
|
||||
| 11 | `usePro` | Pro Mode | `Checkbox` | Higher quality generation (more credits) | Sora |
|
||||
| 12 | `fluxUltraRaw` | Raw Mode | `Checkbox` | More natural, less processed look | Flux Ultra |
|
||||
| 13 | `transparent` | Transparent Background | `Checkbox` | Generate image with transparent background | OpenAI |
|
||||
|
||||
@@ -180,7 +180,7 @@ The type "lies" — it claims every flag is present and boolean, when at runtime
|
||||
- The wire payload is still sparse (Phase 2 stays — half the win was the bytes)
|
||||
- **The flag-removal safety net still works**: `FeatureFlagKey` is the keyspace, so removing a flag from the registry shrinks the union and produces a type error at every consumer (including destructure sites)
|
||||
|
||||
**What we lose:** the type doesn't enforce write safety (`features.X = false` compiles even though wire payload never produces `false`). Acceptable — no consumer writes to the cache except [SettingsCard.tsx:334](../src/components/Account/SettingsCard.tsx#L334), and that one assignment is internal optimistic-cache state, not the wire payload.
|
||||
**What we lose:** the type doesn't enforce write safety (`features.X = false` compiles even though wire payload never produces `false`). Acceptable — no consumer writes to the cache except [SettingsCard.tsx:335](../src/components/Account/SettingsCard.tsx#L335), and that one assignment is internal optimistic-cache state, not the wire payload.
|
||||
|
||||
### Phase 4 — Benefits realized
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@ install. Each app is served from its own platform-owned subdomain
|
||||
## Tokens
|
||||
|
||||
- RS256, signed by `BLOCK_TOKEN_PRIVATE_KEY`, verified via JWKS.
|
||||
- 15-minute lifetime by default; 5-minute lifetime for `block:settings:*` scopes.
|
||||
- 15-minute lifetime by default; 5-minute lifetime for `block:settings:*` scopes
|
||||
— a RETIRED scope family (see the Scopes table), so a manifest can no longer
|
||||
declare it and that shorter lifetime is unreachable today.
|
||||
- Claims: `iss`, `aud`, `sub` (`user:<id>` or `anon`), `iat`, `nbf`, `exp`,
|
||||
`jti`, `blockId`, `appId`, `blockInstanceId`, `ctx`, `scopes`,
|
||||
`buzzBudget?`.
|
||||
@@ -57,12 +59,12 @@ check at request time (`enforceContextBinding`).
|
||||
| Scope | Bind | Notes |
|
||||
| -------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `models:read:self` | `query.id == ctx.modelId` | |
|
||||
| `media:read:owned` | non-anon `sub` | |
|
||||
| `buzz:read:self` | non-anon `sub` | |
|
||||
| ~~`media:read:owned`~~ | — | **REMOVED** from the scope registry (purely decorative — no endpoint ever checked it). A manifest declaring it is REJECTED. The OAuth `MediaRead` bit is unaffected |
|
||||
| `buzz:read:self` | non-anon `sub` | **required for EVERY host-mediated buzz read**, `blocks.getMyBuzzBalance` included — it is no longer scope-free. A token without it gets `block lacks buzz:read:self scope` (FORBIDDEN) |
|
||||
| `social:tip:self` | non-anon `sub` | |
|
||||
| `user:read:self` | non-anon `sub` | viewer identity — read via the `useViewer()` hook (`GET_VIEWER` bridge → `blocks.getMyViewer`). Also gates the **deprecated** `/api/v1/blocks/me` REST route (retiring) |
|
||||
| `ai:write:budgeted` | positive `buzzBudget` | |
|
||||
| `block:settings:read` / `:write` | `query.blockInstanceId == claims.blockInstanceId` | + caller-is-installer at issuance; `SKIP_OAUTH_CHECK` |
|
||||
| ~~`block:settings:read` / `:write`~~ | — | **REMOVED** from the scope registry (no runtime capability ever verified them; the settings paths authorize on valid-token + app-developer + installer-resolution). A manifest declaring either is REJECTED |
|
||||
| `apps:storage:read` / `:write` | scope present on `claims.scopes` per op | per-app KV store (App Storage); no OAuth bit (`SKIP_OAUTH_CHECK`) — gated by the approved-scope snapshot + `resolveStorageContext` |
|
||||
|
||||
Unknown scopes are rejected at runtime (deny-by-default in middleware).
|
||||
@@ -111,7 +113,9 @@ fine-grained tool for ops.
|
||||
- **Ownership escalation**: `block:settings:*` tokens require caller
|
||||
is the install's `installedByUserId` at issuance. The check is
|
||||
authoritative at issue time; deleted-publisher installs (FK SET NULL)
|
||||
fail closed.
|
||||
fail closed. ⚠️ The scope family is RETIRED (see the Scopes table), so this
|
||||
check still exists in `block-tokens/index.ts` but nothing can reach it —
|
||||
the scope cannot be declared, approved or minted.
|
||||
|
||||
## BLOCK_INIT contract
|
||||
|
||||
@@ -310,6 +314,11 @@ Civitai Buzz is split into spendable pools — **blue** (purchased), **green**
|
||||
`blocks.getMyBuzzBalance` mutation, which returns `{ blue, green, yellow }` for
|
||||
the token's subject (other account types — red / cash / creator-program — are
|
||||
omitted). This backs the SDK `useBuzzBalance()` hook + the account picker.
|
||||
**Declare `buzz:read:self`** — this read requires it, like every other
|
||||
host-mediated buzz read. It used to be scope-free (gated on an authoring
|
||||
capability instead); that capability gate was removed from the runtime, and the
|
||||
user's own scope grant is the authority now. A token without the scope gets
|
||||
`block lacks buzz:read:self scope`.
|
||||
- **Choose the funding pool**: a workflow submit body may carry `accountType`
|
||||
(`blue | green | yellow`). It is honored **preferred-first** while the maturity
|
||||
policy clamp still applies (a SFW-domain block can't widen to a mature currency);
|
||||
@@ -319,6 +328,39 @@ Civitai Buzz is split into spendable pools — **blue** (purchased), **green**
|
||||
`spentAccountType` — the `accountType` of the largest _realized_ debit — so a
|
||||
block can attribute spend after the fact (internal-only accounts are omitted).
|
||||
|
||||
### The user's per-app spend limit (consent budget)
|
||||
|
||||
A viewer who grants `ai:write:budgeted` may also set a **daily Buzz limit for that
|
||||
one app**, stored on their grant row (`app_user_scope_grants.buzz_budget_per_day`).
|
||||
It is the only one of the three spend ceilings the user chooses:
|
||||
|
||||
| Ceiling | Scope of the key | Who set it |
|
||||
| --- | --- | --- |
|
||||
| Platform per-user daily cap | one user, ALL their apps | the platform |
|
||||
| Per-app aggregate cap | one app, ALL its users | the platform |
|
||||
| **Consent budget** | one (user, app) pair, per UTC day | **the user** |
|
||||
|
||||
- **Both apply; the tighter one binds.** The consent budget is bounded above by the
|
||||
platform per-user daily cap, so it can only ever narrow. `null` (the default, and
|
||||
the state of every grant made before the field existed) means "no limit of my own"
|
||||
and behaves exactly as it did before.
|
||||
- **Set at consent time** in the permission modal (shown only when the scope being
|
||||
granted is `ai:write:budgeted` — a limit next to "read your username" bounds
|
||||
nothing), and **changed, cleared or simply read afterwards** on
|
||||
**Apps → Permissions** (`/apps/activity`). Both write through
|
||||
`blocks.grantScopes`, whose `buzzBudgetPerDay` input has three distinct states: a
|
||||
number sets/replaces, `null` clears, and an **omitted** key leaves the stored value
|
||||
alone (so re-consenting to an unrelated scope can never wipe a limit).
|
||||
- **What an app sees when it binds.** The submit is refused before any spend with a
|
||||
`failed` snapshot whose error names the user's own number — e.g. `app Buzz limit
|
||||
reached: 400 already spent today by this app on your behalf, this generation may
|
||||
cost up to 150, your limit for this app is 500`. Unlike the platform per-app cap
|
||||
(a platform secret), this ceiling is the user's own setting, so telling the app is
|
||||
what makes the rejection actionable: surface it and let the user raise the limit.
|
||||
- **Post-paid jobs reserve the CEILING and settle to actual**, on this counter exactly
|
||||
as on the platform one — so a job that reserves 5,000 and bills 200 gives back 4,800
|
||||
when it reaches a terminal state.
|
||||
|
||||
## Publish / review / deploy lifecycle (no trust on push)
|
||||
|
||||
The build + deploy of new iframe code is gated entirely on **moderator
|
||||
|
||||
@@ -146,8 +146,17 @@ every measured number are in [paid-model-loading-coverage.md](paid-model-loading
|
||||
model with a loadable file. The LORA/TI/VAE/LoCon/DoRA/Upscaler branch is unchanged.
|
||||
- [x] drop the `CoveredCheckpoint` conjunct, and allow `Diffusers` while keeping Core ML and ONNX
|
||||
excluded — [the numbers](paid-model-loading-coverage.md#what-changes-in-numbers)
|
||||
- [x] **checkpoints require a SafeTensor weight file** —
|
||||
`20260909180000_generation_coverage_next_safetensor_checkpoints`, 2026-09-09. Narrows the
|
||||
2026-09-08 view: Diffusers stays loadable for every type *except* checkpoints, and
|
||||
`CoveredCheckpoint` returns as a disjunct excusing 6 auction-resident versions.
|
||||
**Written, not yet applied to any environment.**
|
||||
- [ ] 🔴 keep `EcosystemCheckpoints` — 62 of 63 checkpoint defaults depend on it
|
||||
- [x] diffed against production 2026-09-08 — nothing loses coverage; [the numbers](paid-model-loading-coverage.md#what-changes-in-numbers)
|
||||
- [x] diffed against production 2026-09-08 — nothing lost coverage *at that point*; [the numbers](paid-model-loading-coverage.md#what-changes-in-numbers)
|
||||
- [ ] 🔴 **2,242 covered checkpoints lose coverage when the SafeTensor migration is applied**
|
||||
(33,811 -> 31,569; 834 with generation history, 6.5M lifetime generations). A narrowing, so
|
||||
there is no safe window — apply it when the readers of `covered` are ready.
|
||||
*Closes when:* applied to production and the covered-checkpoint count reads 31,569.
|
||||
- [ ] **Set `usageControl = 'ExternalGeneration'` on the 36 mislabelled API versions.** All
|
||||
published, none POI, coverage preserved 36/36. Mod-only to set via the app, so it is a direct
|
||||
DB write.
|
||||
@@ -239,9 +248,11 @@ the platform second.
|
||||
- [ ] **C11 — retire auctions.** ([868ktt5b2](https://app.clickup.com/t/868ktt5b2)) Do not scope
|
||||
until 868gtq1kt (splitting featuring out of auctions) has an answer — auctions do two jobs
|
||||
and paid loading replaces one. ~89 files under `src/`.
|
||||
- [x] the `CoveredCheckpoint` conflict is resolved by removing it from coverage (Phase 1.6), so
|
||||
the auction job can no longer un-cover a paid checkpoint. What remains is deciding whether
|
||||
that job should keep writing rows nothing reads.
|
||||
- [x] the `CoveredCheckpoint` conflict is resolved by removing it as a coverage *conjunct*
|
||||
(Phase 1.6), so the auction job can no longer un-cover a paid checkpoint. It survives as a
|
||||
disjunct covering 6 auction-resident versions that lack a SafeTensor file — those would lose
|
||||
coverage on the next auction prune, but none is loadable, so none can have been paid for.
|
||||
What remains is deciding whether that job should keep writing rows nothing else reads.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ This is the thing an earlier reading of these docs got wrong, and it inverted a
|
||||
| `CoveredCheckpoint` | 514 rows | Auction-won community checkpoints — a **residency proxy**. Written and pruned weekly by `handle-auctions.ts`. **This is what paid loading replaces.** (638 versions are covered *as checkpoints* — the rest come from `EcosystemCheckpoints`.) |
|
||||
| `EcosystemCheckpoints` | 125 | The generator's **default model per ecosystem**. **62 of the 63 checkpoint defaults are covered through it — and zero through `CoveredCheckpoint`.** Not a loophole; the registry that keeps the generator working. |
|
||||
|
||||
Dropping `CoveredCheckpoint` is the feature. Dropping `EcosystemCheckpoints` would remove the
|
||||
Dropping `CoveredCheckpoint` **as a conjunct** is the feature — it no longer gates anything. It
|
||||
survives as a *disjunct* excusing 6 auction-resident checkpoints from the SafeTensor requirement, and
|
||||
is deleted when the auction stops writing rows. Dropping `EcosystemCheckpoints` would remove the
|
||||
default model from half the ecosystems the generator supports — see
|
||||
[the defaults audit](#the-defaults-audit).
|
||||
|
||||
@@ -89,8 +91,23 @@ contributes. Earlier drafts of these docs used 514 for both, which is what made
|
||||
fail to add up.
|
||||
|
||||
155 published, licensed, standard checkpoints on supported base models were blocked **only** by file
|
||||
format: 132 Diffusers, 21 Core ML, 2 ONNX. Diffusers is loadable (Justin, 2026-09-08); Core ML and
|
||||
ONNX are inference-runtime formats rather than servable weights and stay excluded.
|
||||
format under `GenerationCoverage`: 132 Diffusers, 21 Core ML, 2 ONNX.
|
||||
|
||||
⚠️ **Diffusers was ruled loadable (Justin, 2026-09-08) and then narrowed back out for CHECKPOINTS on
|
||||
2026-09-09.** The loader serves SafeTensor only, so the checkpoint branch of `GenerationCoverageNext`
|
||||
now requires a SafeTensor weight file (migration
|
||||
`20260909180000_generation_coverage_next_safetensor_checkpoints`) and `checkLoadable` in
|
||||
`resource-load.service.ts` refuses everything else with `unsupported-format`. Diffusers remains
|
||||
accepted for **every other model type** — the shared `EXISTS` is unchanged, so the Core ML / ONNX
|
||||
deny-list still governs LoRA/TI/VAE/LoCon/DoRA/Upscaler.
|
||||
|
||||
🔴 **The SafeTensor narrowing took 2,242 checkpoints back out.** Measured 2026-09-09 against the
|
||||
production replica: covered checkpoints **33,811 -> 31,569**, total view rows **933,851 -> 931,609**
|
||||
(every row of the delta a checkpoint; textual inversions unchanged at 6,299, all 514 auction rows
|
||||
retained). 834 of the 2,242 have any generation history — 6.5M lifetime generations, 0.43% of all
|
||||
checkpoint generation. Scoping matters: putting the rule on the shared `EXISTS` instead would have
|
||||
removed 3,287 textual inversions carrying **1.39 billion** generations, more than every SafeTensor TI
|
||||
combined.
|
||||
|
||||
### The loader population, split by bucket
|
||||
|
||||
|
||||
@@ -169,6 +169,25 @@ is dead code. Removing it widens covered checkpoints by roughly two orders of ma
|
||||
must stay**, because 62 of 63 checkpoint defaults are covered through it and none through
|
||||
`CoveredCheckpoint`. See [coverage](paid-model-loading-coverage.md#the-two-tables-do-opposite-jobs).
|
||||
|
||||
⚠️ **Amended 2026-09-09.** `CoveredCheckpoint` is no longer a conjunct — Justin's condition holds —
|
||||
but it returns as a **disjunct** in `20260909180000_generation_coverage_next_safetensor_checkpoints`,
|
||||
excusing 6 auction-resident checkpoints from the new SafeTensor requirement. Auction membership no
|
||||
longer decides coverage; it stands in for residency until C11 retires the job, and is deleted with it.
|
||||
|
||||
### 2.7 ⚠️ Diffusers is loadable — except for checkpoints
|
||||
|
||||
Justin ruled Diffusers loadable on 2026-09-08, and the first `GenerationCoverageNext` migration
|
||||
removed it from the excluded-format list for every type. The loader serves **SafeTensor only**, so
|
||||
the checkpoint branch was narrowed back on 2026-09-09 — 174 Diffusers checkpoints sit among the
|
||||
2,242 versions that lose coverage. Diffusers is untouched for LoRA/TI/VAE/LoCon/DoRA/Upscaler.
|
||||
|
||||
**Open:** whether Justin accepts the narrowing as an implementation constraint, or wants the loader
|
||||
to grow Diffusers support. *Decides:* Justin. *Closes when:* he answers here, or the migration is
|
||||
applied to production with the narrowing intact.
|
||||
|
||||
@dev: The loader can only serve SafeTensor today. OK to drop Diffusers/GGUF/PickleTensor checkpoints
|
||||
from coverage (2,242 versions, 0.43% of checkpoint generation), or should the loader learn them?
|
||||
|
||||
### 2.4 ✅ The C4 webhook — not now
|
||||
|
||||
**Closed 2026-09-08: no.** Both reasons to build it went away on the same day.
|
||||
|
||||
@@ -240,15 +240,18 @@ The premise of the feature is that the generator stops being restricted to a cur
|
||||
2026-09-08 this is scoped and decided; the full model, the audit and every measured number live in
|
||||
[paid-model-loading-coverage.md](paid-model-loading-coverage.md). In short:
|
||||
|
||||
- **`CoveredCheckpoint` goes away.** It is the auction's residency proxy, it has four uses and all
|
||||
four are generation, and dropping it widens covered checkpoints by roughly two orders of magnitude
|
||||
([the numbers](paid-model-loading-coverage.md#what-changes-in-numbers)).
|
||||
- **`CoveredCheckpoint` stops gating.** It is the auction's residency proxy, it has four uses and all
|
||||
four are generation, and removing it *as a conjunct* widens covered checkpoints by roughly two
|
||||
orders of magnitude ([the numbers](paid-model-loading-coverage.md#what-changes-in-numbers)). It
|
||||
remains as a *disjunct* excusing 6 auction-resident checkpoints from the SafeTensor rule, and is
|
||||
deleted with the auction.
|
||||
- **`EcosystemCheckpoints` stays.** It is the generator's default model per ecosystem — 62 of the 63
|
||||
checkpoint defaults are covered through it and none through `CoveredCheckpoint`. Removing it would
|
||||
strip the default model from half the supported ecosystems.
|
||||
- **`GenerationBaseModel` stays as the gate.** It marks the base models where the orchestrator has
|
||||
extended checkpoint/diffuser support, i.e. where community models can run.
|
||||
- **Diffusers becomes loadable**; Core ML and ONNX stay excluded.
|
||||
- **Checkpoints must carry a SafeTensor weight file** (2026-09-09); GGUF, PickleTensor, Diffusers,
|
||||
Core ML, ONNX and unset are all unloadable. Diffusers stays accepted for every other type.
|
||||
- **File-less models never touch the loader**, and "file-less" means *no loadable file*, not *no file
|
||||
row* — 36 API models carry a `Training Data` archive and would otherwise read as loadable.
|
||||
|
||||
@@ -343,7 +346,9 @@ deciding anything.
|
||||
- **`CoveredCheckpoint` stops gating generation**; `EcosystemCheckpoints` and `GenerationBaseModel`
|
||||
stay. Coverage means *allowed to generate*; residency is the orchestrator's axis.
|
||||
- **Only base models in `GenerationBaseModel` are loadable.** Everything else is out of scope for v1.
|
||||
- A checkpoint needs a **correct model file** to be loadable; file-less API models never are.
|
||||
- A checkpoint needs a **SafeTensor** weight file to be loadable (2026-09-09); file-less API models
|
||||
never are, and a GGUF/PickleTensor/Diffusers checkpoint gets a different refusal —
|
||||
`UNLOADABLE_MESSAGES` in `resource-load.service.ts` is the single source of both.
|
||||
- A load that never finishes is **refunded**.
|
||||
- The purchase path refuses anything **not in `GenerationCoverageNext`** (composed with ecosystem
|
||||
type support by `isGenerationEligible`), which is how the `RentCivit` rule is enforced without
|
||||
|
||||
@@ -61,8 +61,8 @@ Mapping each input type to the ecosystem(s) whose handler produces it (router: `
|
||||
| Input type | Ecosystems (ECO keys) | Handler |
|
||||
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `TextToImageInput` | `SD1`, `SD2`, `SDXL`, `Pony`, `Illustrious`, `NoobAI`, `Flux1`, `FluxKrea`, `Chroma`, `HiDream`, `PonyV7` | `stable-diffusion.handler.ts`, `flux.handler.ts`, `chroma.handler.ts`, `hi-dream.handler.ts`, `pony-v7.handler.ts` |
|
||||
| `ComfyImageGenInput` | `Anima`, `Ernie`, `Lens`, `HiDream-O1` + SD-family img2img/face-fix/hires-fix (already covered by the SD ecosystems above) | `anima/ernie/lens/hi-dream-o1.handler.ts`, `comfy-input.ts` |
|
||||
| `SdCppImageGenInput` | `ZImageTurbo`, `ZImageBase`, `Qwen` | `z-image.handler.ts`, `qwen.handler.ts` |
|
||||
| `ComfyImageGenInput` | `Anima`, `Ernie`, `Lens`, `HiDream-O1`, `ZImageTurbo`, `ZImageBase`, `Qwen` + SD-family img2img/face-fix/hires-fix (already covered by the SD ecosystems above) | `anima/ernie/lens/hi-dream-o1/z-image/qwen.handler.ts`, `comfy-input.ts` |
|
||||
| `SdCppImageGenInput` | _(none — ZImage and Qwen moved to comfy; see the `ComfyImageGenInput` row)_ | — |
|
||||
| `Flux2KleinImageGenInput` | `Flux2Klein_9B`, `Flux2Klein_9B_base`, `Flux2Klein_4B`, `Flux2Klein_4B_base` | `flux2-klein.handler.ts` |
|
||||
| `ComfyVideoGenInput` | _(no active ecosystem — see note)_ | — |
|
||||
| `ComfyLtx2VideoGenInput` | `LTXV2` | `ltx.handler.ts` |
|
||||
@@ -74,7 +74,7 @@ Mapping each input type to the ecosystem(s) whose handler produces it (router: `
|
||||
### Traps — lookalike ecosystems that are EXTERNAL (must NOT be gated)
|
||||
|
||||
- **`Flux2`** (plain) → external (`flux2` engine). Only **`Flux2Klein*`** is self-hosted.
|
||||
- **`Qwen2`** → external (`fal`). Only **`Qwen`** (sdcpp) is self-hosted.
|
||||
- **`Qwen2`** → external (`fal`). Only **`Qwen`** (comfy) is self-hosted.
|
||||
- **All `Wan*` ecosystems** → external (FAL) today. Out of scope.
|
||||
|
||||
> **Decision 1 — RESOLVED: clean ecosystem-key granularity.** Every self-hosted ecosystem is all-or-nothing at the ecosystem-key level. No flag-conditional cases, no version-level lists. The static `selfHosted: true` flag fully describes the set.
|
||||
|
||||
@@ -285,8 +285,8 @@ per-graph scopes. The lib grew `defineGraph({ scope })` (graph-level default sco
|
||||
field `scope` — including `[]`, the bare-key opt-out — wins; mounted children
|
||||
keep their own fn). The layout, mirroring v1's groups: every family graph and
|
||||
branch member carries `defineGraph({ scope: familyScope })` (ecosystem group id, else key —
|
||||
wan versions and klein variants share buckets); `SEED` and `controlNetsDef`
|
||||
opt out to bare keys (v1 stores them globally); images/video wrap their def fns
|
||||
wan versions and klein variants share buckets); `SEED`, `controlNetsDef` and
|
||||
`controlVideoDef` opt out to bare keys (v1 stores them globally); images/video wrap their def fns
|
||||
in `workflowScoped` (per-workflow buckets); the hubs scope `ecosystem` per
|
||||
output type, `quantity` per workflow only on draft, `enhancedCompatibility`
|
||||
per family bucket; and the turbo-variant families (zimage/boogu/krea2/anima/ernie/lens/mage-flow — all seven ported
|
||||
@@ -464,7 +464,7 @@ home); full suite + typecheck + lint green; Briant reviews the final diff.
|
||||
| video: sora2 | DONE | DONE | AR options per resolution (txt2vid only), usePro, durations 4/8 |
|
||||
| video: hunyuan (HyV1) | DONE | DONE | cfg/steps presets, familyResources, 480p AR set |
|
||||
| video: flux3-video | DONE | DONE | First/Last frame slots on img2vid; v1's draft→resolution forward dep is dead, resolution unconditional (probed) |
|
||||
| video: minimax (MiniMaxH3, api/comfy) | DONE | DONE | tagged branch on version: comfy carries loras/seed/turbo-shaped steps, api is bare; ref2vid takes up to 9 refs (`variantOf`, NOT a prefix match — bit us) |
|
||||
| video: minimax (MiniMaxH3, api/comfy) | DONE | DONE | tagged branch on version: comfy carries loras/seed/turbo-shaped steps, api is bare; ref2vid takes up to 9 refs (`variantOf`, NOT a prefix match — bit us). `controlVideo` (H3 Fun ControlNet Union) is comfy + txt2vid only — the control operation REPLACES imageToVideo, so there is no frame/reference slot to share it with; its five preprocessor keys are the `preprocessVideo` set, not the image ControlNet set |
|
||||
| video: happy-horse (v1.0/v1.1) | DONE | DONE | AR family keyed `resolution|version` (v1.1 widens the set); vid2vid:edit carries video + refs + audioSetting |
|
||||
| video: veo3 (fast/standard) | DONE | DONE | workflowVersions inert (same list both workflows); ref2vid pins duration to 8s at the boundary; version enum defaults '3.1' (3.0 endpoints retired) |
|
||||
| video: vidu (Q1/Q3) | DONE | DONE | image-driven workflows emit NO aspectRatio (v1 hides the node; handler derives from source — probed); Q3 ref2vid rewrites to img2vid in `reconcile.ts`; Q3 resolution-scaled AR dims |
|
||||
@@ -475,7 +475,7 @@ home); full suite + typecheck + lint green; Briant reviews the final diff.
|
||||
| model3d: polygen (Meshy v6/v7) | DONE | DONE | `polygenVersion` flag-gated (meshyV7Generator) AND workflow-clamped (v7-on-text → v6) in both input and output transforms; v7-only knobs null out per version/image-count; v7 has no seed |
|
||||
| model3d: tripo / hunyuan3d / pixal3d / trellis2 | DONE | DONE | image-to-3D only; pixal3d and trellis2 are field-identical (one factory, two instances for their own family scopes); hunyuan keeps its `hunyuan*` field prefixes, mapped back in the handler |
|
||||
| model3d hub | DONE | DONE | ecosystem scoped 'model3d', default PolyGen; the four newer 3D ecosystems are flag-hidden fail-closed via the shared getEcosystemStates |
|
||||
| standalone workflows (img2img:upscale / remove-background / preprocess, vid2vid:upscale / interpolate, img2meta, prompt:enhance) | DONE | DONE | seven arms on a state-only `workflowKind` dispatch at the root (the oracle wire has no such key); priority/outputFormat moved to the ROOT gated on image output, matching v1 — they apply to standalone image workflows too. The upscale batch reset (v1 transform) is a `correct`; preprocess kind specs import from the v1 module (they mirror @civitai/client, not the engine). The two empty panels (img2meta, prompt:enhance) are bare graphs. Step creation stays in the submit service keyed on workflow — data parity covers it, no lane handlers needed |
|
||||
| standalone workflows (img2img:upscale / remove-background / preprocess, vid2vid:upscale / interpolate / preprocess, img2meta, prompt:enhance) | DONE | DONE | eight arms on a state-only `workflowKind` dispatch at the root (the oracle wire has no such key); priority/outputFormat moved to the ROOT gated on image output, matching v1 — they apply to standalone image workflows too. The upscale batch reset (v1 transform) is a `correct`; preprocess kind specs import from the v1 module (they mirror @civitai/client, not the engine). The two empty panels (img2meta, prompt:enhance) are bare graphs. Step creation stays in the submit service keyed on workflow — data parity covers it, no lane handlers needed |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
This plan addresses the migration to support multiple sub-domains where each supports one primary Buzz currency (Yellow or Green) while allowing Blue Buzz everywhere. The implementation enforces currency restrictions at both transaction and UI levels.
|
||||
|
||||
> **Shipped — with a different hook signature than the blocks below.** `useAvailableBuzz(baseTypes: BuzzSpendType[] = [])` takes an array, not an `includeBlue` boolean, and blue is **not** included by default: `useQueryBuzz()` with no argument totals the domain's own type alone. The Phase 2 code blocks are the original proposal; read `src/components/Buzz/useAvailableBuzz.ts` and `src/components/Buzz/useBuzz.ts` for the shipped shape.
|
||||
|
||||
|
||||
## Current Architecture Analysis
|
||||
|
||||
### Current Buzz Implementation
|
||||
|
||||
@@ -63,6 +63,9 @@ new code. Recorded because two are repeats of things this file already documents
|
||||
- [x] **`Images to Ingest` is `informational`** — the page has no actions and the count is upload
|
||||
throughput, so summing it into the Images badge reads as a review backlog whenever the scanner
|
||||
stalls.
|
||||
- The flag reached the dashboard total only; the sidebar's `rollupFor` kept summing it until the
|
||||
stuck-scan change (`feat/image-scan-stuck-alert`), which also switched the badge to count stuck
|
||||
scans (`stuckIngestion`) instead of every pending upload from the last 5 days.
|
||||
- [x] **The Most reported rewrite evaluated its seventeen subplans below the sort**, i.e. for every
|
||||
qualifying report rather than the twenty kept — Postgres cannot project through a `Sort`, and the
|
||||
comment claimed the opposite. The LIMIT is taken in a CTE and the ids resolved outside it.
|
||||
|
||||
@@ -32,7 +32,7 @@ Default resolution 1024x1024 (2K capable). Bilingual (CN/EN) text rendering.
|
||||
```
|
||||
|
||||
Base-model flip (Other -> Boogu) script: `<local-path>/AppData\Local\Temp\boogu-flip.mjs` (dry-run default; `--execute` to write). Validated via dry-run; run after the v5.0.1868 deploy is live in prod.
|
||||
3. **Engine string + edit operation contract — orchestrator's call.** ZImage uses `engine: 'sdcpp', ecosystem: 'zImage'`. Boogu's engine (comfy? sdcpp? a new one?) and whether edit is `operation: 'editImage'` vs image-presence-inferred is whatever the orchestrator implements. Confirm with orchestrator team.
|
||||
3. **Engine string + edit operation contract — orchestrator's call.** ZImage uses `engine: 'comfy', ecosystem: 'zImage'`. Boogu's engine (comfy? sdcpp? a new one?) and whether edit is `operation: 'editImage'` vs image-presence-inferred is whatever the orchestrator implements. Confirm with orchestrator team.
|
||||
|
||||
## Gating mechanism (answer to "Flipt or ecosystem mgmt?")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user