---
name: gen3d-character-workflow
description: "Use exclusively for ForgeaX Gen3D character production: character model generation or import, rigging, Idle/Move motion, character inspection, playable export, Engine validation, and same-Job recovery. Not for props or environments."
---

# Gen3D · 3D角色制作与游戏交付

Gen3D only produces 3D characters. Explicitly use `--slot characters` for new
model generation and imports. Do not suggest props, environments, or generic
test objects, even for a provider connectivity test. If the character route is
blocked, identify the missing contract; never switch to `meshes`, remove the
triangle/texture requirements, or substitute a mock artifact to bypass it.
Existing historical `meshes` assets and Jobs may still be inspected and
recovered without relabelling their identity; they are not new creation options.
A character's source model,
rig, motions, slot mapping, and playable export are distinct deliverables.
Inspect `capabilities` first when continuing a role workflow: its
`semanticCapabilities` distinguishes planned, partial, and implemented behavior
from experimental and live-evidence status. An old tool alias or a catalog row
does not authorize calling an unimplemented operation. Report the exact missing
step instead of claiming that a static GLB completes the character.

Run commands from the game directory. The command is pinned to this installation;
do not use a global Gen3D binary, vendor MCP, `forgeax_generate_3d`, or direct
provider HTTP.

## Current provider availability

Meshy generation uses the installed plugin's explicit `--transport direct` route with the user's Meshy API Key. Text preview/refine, image, multi-image (1–4), remesh, Rig and one-preset Animation are supported as distinct confirmed stages. Direct Rig requires this account’s registered textured source task and exact local GLB; Animation requires its successful current Rig task and registered GLB. The runtime verifies source/Rig Job, task, output bytes and credential scope before submission. Unknown POST outcomes stay on the original Job; never retry or fall back to another input route. New generation defaults to Meshy 7.1. Meshy gateway generation remains paused. Preserve historical Jobs and never retry unknown submissions. Enter keys only through authenticated Settings or private environment configuration, never in chat. Text generation with textures has two separately charged stages; refine inherits its preview model. Images go directly as byte-bound data URIs, without ForgeaX/COS upload. Provider success, local download/registration and visible preview are separate acceptance steps.

For the Rodin/VISVISE gateway candidate, distinguish client support from live
acceptance. Rodin character generation uses `mesh_mode=Raw`, a bounded
`quality_override` (500–30,000) and `material=PBR`; measure the returned GLB.
VISVISE new model generation is image-only, using the account's current exact
algorithm identifier; pure text is rejected before payment.
Before a new VISVISE Rig, run `{{CLI}} prepare-rig-input --json --provider visvise
--asset <registered character GLB>`. This local operation uses installed Blender
5.2.0 LTS only for format conversion, preserves the source and records FBX
bytes/tool provenance. It does not upload, bind bones, add weights or create
animation. If preparation fails, report the specific blocker. Use its registered
FBX path for the separately confirmed Rig. For Motion, use the same account's
successful current Rig FBX, never the original unrigged FBX. The runtime uploads
confirmed bytes and handles the gateway URL internally.
Preserve original FBX/ZIP outputs. A local conversion failure is resumed on the
same completed provider Job without another submission. BVH or animation-only
outputs are not complete characters. A converted GLB still needs visible
playback verification; Engine import and playback remain separate gates.

## Visual review in the conversation

For a request to view a character, use its existing registered Asset Path and
selected Rig/Motion resource. Viewing a result is a local read/render operation;
new generation, animation and Engine writes follow their own workflow below.

- After model creation, show a real preview image before the appearance review.
  Read `{{CLI}} preview --json --asset <Asset Path>` for a recorded preview.
  If none exists, or a particular Rig/Motion must be shown, use
  `{{CLI}} render-preview --json --asset <Asset Path> --resource-path <registered GLB>
  --out <absolute unused PNG path> --size 768 --style shaded`. Omit
  `--resource-path` for the source model. Inspect the returned PNG, then embed
  that absolute local file as an image in the conversation, with the character
  name and a short caption. A texture atlas is not a character preview.
- For rotation, skeleton inspection or animation playback, open the running
  Workbench in the host's browser panel, select the matching character and its
  registered motion, and verify the visible selection and play/pause controls.
  Keep the process alive while the user reviews it. In Codex use its in-app
  browser or `open_in_codex` when available. A `.glb` attachment alone does not
  provide an interactive 3D viewer in the conversation.
- To reopen an exact selection, read `{{CLI}} preview-selection --json
  --asset <Asset Path> --resource-path <registered GLB> --clip-index <source index>`.
  Omit the resource for the source model and the clip for a static view. Append
  the returned `locator` fragment to the current authenticated Workbench URL
  when opening the panel. Do not copy its authentication token into chat.
  The locator binds the project, source/resource hashes and source clip name;
  mismatches must stop, never fall back to another character. A returned
  `preview.absolutePath` is an existing source image, not proof of animation.
  For a derived Rig/Motion, render that registered resource as described above.
- Workbench's View menu (**视图**) contains **保存图片** for a local capture of the
  current camera/pose. **复制对话上下文**
  copies the selected asset/resource context for the user to paste into their
  chat; it does not send a message. When that context is received, inspect the
  selection and show its picture before discussing the requested change.
- Lead with the visual result and one useful next action. Keep technical logs
  in details. Label local still images as previews; report animation and actual
  Engine playback only after observing their respective running surfaces.
  A visual review does not approve another paid stage.

1. Verify identity with `{{CLI}} capabilities --json` when the extension may
   not be enabled.
2. If setup is uncertain, run `{{CLI}} doctor --json`.
   Doctor is local-only: configured, adapter-ready, gateway-discovered, and
   live-verified are separate. It does not spend quota.
   To check a named provider through the configured ForgeaX gateway, use
   `{{CLI}} probe-provider --provider hunyuan|rodin|visvise --json`
   (choose one provider). This explicit GET-only diagnostic reports catalog and
   safe task-query reachability, not production acceptance. It never uploads,
   creates a Job, or retries/downgrades an existing Job. Treat its pipeline
   requirements as unverified boundaries; VISVISE COS/ZIP handling and valid
   account algorithms must be confirmed at the gateway, not bypassed with a
   direct supplier call. Workbench exposes the same check under Advanced.
3. List durable evidence with `{{CLI}} jobs --json` and `{{CLI}} assets --json`.
   Identity is a game-relative Asset Path under `assets/3d/characters` or
   `assets/3d/meshes`, never a Transfer URL.
   For a selected row, read `{{CLI}} job-detail --json --job <jobId>` or
   `{{CLI}} asset-detail --json --asset <Asset Path>`. These are read-only
   projections: they expose safe status and file identity fields, while
   raw provider errors, routes, credentials, and remote URLs remain private.
   Safe error fields (`phase`, `code`, `httpStatus`, a sanitized reference ID,
   and the durable `jobId`) may be shown to explain recovery.
4. Resolve a Request Draft with `{{CLI}} resolve-generation --json` plus the
   draft flags (`--name`, `--provider`, `--action`, `--mode`, `--prompt` or
   `--image` / `--views`, optional `--params`, `--slot`, `--texture`,
   `--polycount`).
   Generate supports the catalog's finite Hunyuan/Rodin/VISVISE routes.
   Multi-view input uses the named `front`, `back`, `left`, `right`, `top`,
   `bottom`, `left_front`, `right_front` slots in that order. Provider limits
   still apply; the CLI retains valid two-image subsets, Hunyuan requires
   `front`, and unknown slots are resolution errors.  The resolver is the
   source of truth for provider-specific support and reports explicit
   conflicts or unsupported values instead of dropping them.
5. If the result is `needs_input`, ask only about the returned issues.
   If `status` is `ready`, show the Provider Route, Plugin Defaults, omissions,
   paid stages, write stages, and `planHash`.
6. `planHash` binds the plan against tampering. It is not human approval.
   Do not invent `--confirm-plan` as a payment gate. `--json generate` that
   only repeats a hash cannot mint a receipt and must fail closed.
7. Paid generate happens through one persistent interactive CLI process. Start
   `{{CLI}} generate` with the resolved draft on a real PTY and read its
   `GEN3D_CONFIRMATION_REQUEST_V1` summary. Show that exact operation, project,
   request/input identities, adapter/transport/model, actual gateway URL,
   account label, effective parameters, omissions, paid/write stages, and the
   confirmation timeout plus receipt validity. Only after the user explicitly
   approves this exact summary may the trusted Agent write `yes` to the same
   PTY. Do not start a second command, invent a `yes` flag, or send a hash as
   approval. The CLI re-resolves the plan and input bytes before consuming its
   one-time in-process receipt. EOF, cancel, timeout, rejection, or a changed
   request fails closed. If the input bytes, route, or resolved plan changes
   after the answer, discard that answer, show the refreshed request summary
   and any new resolution issues, and start a new confirmation session; never
   execute the new plan with the old `yes`. The PTY and test input do not prove
   human identity; record test-driven confirmation as test evidence only.
   Resume an in-flight job with `{{CLI}} resume --json --job <jobId>`.
   For `submission_unknown` / `upload_unknown`, attach the recovered task or
   upload URL; never POST or upload again.
   A concurrent duplicate of the same prepared request reuses its current
   attempt and Job, including when the first request finishes quickly. After a
   terminal Job, a newly confirmed generate is an explicit new attempt and may
   create a new Job; `planHash` identifies request consistency and is not a
   permanent deduplication key.
   Resume and attach require the Job's bound gateway URL. New Jobs also bind a
   SHA-256 fingerprint of the configured credential without storing the secret;
   the account label remains display metadata. Older Jobs without that
   fingerprint can only be checked against their recorded URL.
   Image and named-view inputs upload one multipart asset per input with
   `purpose=model_input`; each transfer witness records its input hash, size,
   MIME, gateway scope, object reference, and expiry.  A partial or uncertain
   upload remains recover-only.  Attach one uncertain input with
   `--input <image|front|back|left|right>` or `--transfer-id <id>` together
   with `--upload-url`; the input selector also accepts the other four named
   views and video when present in the saved Job. The recovered URL must
   identify the complete original input bytes. Attach before resuming the same Job.
8. Engine writes use the host pin only. Start each write in one persistent
   interactive CLI process on a real PTY: `{{CLI}} stage-target`,
   `{{CLI}} deliver --asset <Asset Path>`, `{{CLI}} stage --asset <Asset Path>`,
   or `{{CLI}} unstage`. Show the exact operation, project, Engine identity,
   file hashes, and expected effect printed before the `Confirm Engine write? [y/N]`
   prompt. Only after the user approves that request may the Agent write `yes`
   to the same waiting PTY. A fresh `--json` command cannot reuse this process's
   receipt; it returns `confirmation-required` without opening a prompt. Mark
   an isolated project as a Stage Target, Deliver the selected asset through
   the official Engine importer, then Stage it for the official Scene Preview.
   Stage records the imported Scene GUID,
   its inspection Scene GUID, Engine canvas and compositor evidence, and the
   restoration witness. Inspect the actual Engine images and render report;
   a successful command or Scout view alone does not prove that the model is
   visible. Unstage removes the Gen3D inspection Pack and stage state while
   retaining the delivered asset, target marker, and reviewable evidence.
   Check the original project files before treating restoration as complete.
9. `{{CLI}} ui` starts a loopback Workbench in this process. An open or idle UI
   records that the extension is alive but does not hold the project business
   lock, so another CLI can perform read-only calls and bounded operations.
   Write/pay/Engine controls fail closed until this same receipt gate is used.
   Scout is not Engine Preview. Closing the UI or receiving SIGINT/SIGTERM
   releases only this process's activity record and listener.
   During a generation, SIGINT/SIGTERM aborts the in-flight request and waits
   for its Job state to settle before releasing the operation lock. An admitted
   POST or upload becomes recover-only; an existing task ID remains resumable
   and is never replaced by a blind submission.
   Workbench generation follows `prepare-generation` → named
   `confirm-generation` (`confirmation: "generate"`) and keeps the opaque
   preparation in the server process.  Workbench resume follows the matching
   `prepare-resume` → `confirm-resume` flow and reuses the same Job, stage,
   task, route, and approved scope.  Both flows call the shared execution core;
   preparation alone does not call a provider; confirmed execution may do so.
   Mock gateway evidence
   describes request shape only and is kept separate from live provider claims.
   Engine controls use `prepare-engine` → named `confirm-engine`; show the
   operation, project, Engine identity, Asset Path, file hashes, and expected
   writes before confirmation. Refresh Stage status from the project after
   CLI or Workbench operations, and show only Engine images bound to the
   recorded Stage identity and hashes.
   Confirmation appears inside the Workbench page, not in an automatic OS
   popup or a separate Terminal window. Interactive CLI confirmation appears
   in its waiting terminal session. Tell the user which surface is waiting and
   what exact operation it authorizes; do not ask them to find an unseen popup.
   A long SHA-256 plan or input identity is not a port number. Loopback ports
   are numeric connection endpoints and are separate from these identities.

If a command fails, report the error and stop the dependent step. Never invent
IDs, curl a provider, or treat Scout/HTTP 200 as Engine Preview.

## Character production

+### Beginner continuation and delivery preflight

For an existing character, read `motion-continuation --json --asset <Asset Path>`
through this same CLI. Its `play` result binds the existing resource, hash and
real clip; show/play that resource without making another Rig or Motion Job.
A `rig` or `motion` result provides the current source-bound Workbench draft:
open its Actions drawer to prepare that exact stage, then use the confirmation
flow below. A `blocked` result keeps existing files; explain its reason rather
than switching supplier, guessing a URL or repeating an unknown request.
New beginner motion offers Hunyuan Walk for verified Hunyuan assets and Meshy walking_2_inplace (ID 692) for a verified direct Meshy source/Rig. Other catalog presets, including Casual_Walk (ID 30), require their exact selected ID. A static catalog is not real-provider acceptance. Meshy Rig costs 5 credits and one preset Animation costs 3 credits; these stages need approval beyond the 30-credit text preview/refine case. Present the concrete source, account route, action and additional cost before its confirmation.

For waiting/reopened tasks, read `jobs` / `job-detail` and their `taskFeedback`.
Use only the backend's safe query/registration actions for the original Job;
upload recovery still needs matched gateway evidence. Preparation expires or
is rejected without submitting. Registered stage output is not Engine playback.

Before joining a game, read `game-delivery-preflight --json --asset <Asset Path>
--motion-ref <registered key>`. Show its exact target and proposed files.
A `needs-mapping` result requires the user's explicit character-only Walk review
before `confirm-game-delivery-settings --json --asset <same path> --motion-ref
<same key> --expected-hash <fresh preflight hash> --confirmed true`.
Then prepare its returned `exportInput` through the existing delivery flow;
review any names-only derivative and obtain separate Engine-write approval.
SDK import, scene binding and observed Engine playback remain distinct.
Users choose a character and action; the Agent consumes hashes/keys internally.

Use the current `capabilities.operations`, provider catalog and resolver as the
executable contract. The following steps must retain the same registered Asset
Path, source hash and current rig fingerprint. A source GLB is not a rig; a rig
is not an animation; a confirmed mapping is not an Engine-visible character.

New `generate --slot characters` requests use the product's measured
`game-ready-character-4k` source preset: at most 30,000 triangles, 4K texture
edges and two materials. This is source admission, not Engine performance
acceptance; the legacy `hero-character` 2K inspection recommendation remains
separate. The resolver
pins the generation face target and PBR textures before payment: Hunyuan
`face_count`, with the current provider-specific budget resolved before payment. Explicit lower targets are respected; conflicting or ignored
budget controls fail closed. Prompt words such as “game-ready” are not a budget.
Do not deliver a high-poly source and silently append a reduction job. Inspect
actual source bytes, complete texture bindings, UVs and normals. A succeeded
provider Job can still have an unqualified source; preserve its outputs without
retrying, and stop before new Rig/Motion or playable export. Current character
snapshots expose byte-bound `sourceQualification` separately from rig, clips
and Engine status. Visual quality and visible animation still require review.

1. Choose `--slot characters` for new character generation. For an existing
   local GLB use `import-file --json --file <absolute path> --name <name>
   --slot characters`. `adopt-working-character --json --file <absolute path>
   --name <name>` can register a locally verified rigged, animated GLB and its
   clips without creating a provider Job or Engine GUID. The source is not
   modified. Browser imports use prepared input references, not arbitrary paths.
   Before continuing a newly generated appearance, read `appearance-review
   --json --asset <Asset Path>` and show its real preview. After the user accepts
   that appearance, save `appearance-review --json --asset <Asset Path>
   --decision approve --expected-hash <current sourceHash>` through this CLI.
   `--decision revoke` withdraws that local review; replacing source bytes makes
   an old review stale. Neither action authorizes Rig, Motion or an Engine write.
   If the user wants a different appearance, `appearance-candidate --json
   --asset <Asset Path>` suggests a separate new candidate name without creating
   a Job or overwriting the old character. Review the new prompt and obtain its
   own paid-generation confirmation before making it.
2. Use `pose`, `rig`, `motion` or `lowpoly` only when the
   capability and resolver accept the selected provider and action. They share
   the same interactive approval and persistent Job core as `generate`; an
   alias cannot bypass confirmation. Pose produces an image, which can be
   explicitly applied as a new local input. Never label that image a 3D model.
3. For a new Hunyuan Rig/Motion, the runtime may reuse the same asset's own
   successful generation/Rig Job COS output. It checks the exact original
   SHA-256/size, output role, gateway/account/credential scope, signed lifetime
   (at least 15 minutes) and downloaded bytes before sending `glb_url`/`fbx_url`.
   A mismatch stops without falling back to another upload. This does not
   recover old unknown uploads, authorize another request or accept a caller's
   `remoteInputUrl`; source Jobs without a suitable saved COS URL retain the
   explicit local-input upload route and its unknown-state safeguards.
   Bind rig/motion requests to recorded model bytes. Hunyuan motion uses the current registered rig FBX;
   VISVISE text/video routes remain distinct. Read current rig data rather than
   inventing `--rig-provenance`. `--force true` requires explicit re-rig review
   and the current fingerprint; expired or unknown work must not silently re-rig.
4. Read `motions --json --asset <Asset Path>`. Catalog IDs are offline metadata,
   not live-service proof. Hunyuan v1 has IDs
   9–16; v2/48-action probing and VISVISE independent skinning are not supported.
5. Read `get-playable-profile --json --asset <Asset Path>`. Available presets
   are `basic-character-v1`, `action-adventure-v1`, `platformer-v1` and
   `blank-custom-v1`. Use `set-playable-profile --json --asset <Asset Path>
   --preset <id>` for the character override; `--clear` removes that override.
   Custom `--slots` is a JSON array of `slotId`, `displayName`, `required`,
   `playbackMode` (`loop|once|freeze_frame`), `speed`, `matchKeywords` and
   `rootMotion` (`preserve|remove_xz|remove_xyz`). Do not silently replace the
   project default. Saving it requires `--save-as-game-default true` and the
   just-observed `--expected-game-profile-version`.
6. Present motion suggestions and required slots for review. Persist the
   selected mapping with `set-playable-motion-mapping --json --asset <Asset Path>
   --mappings <JSON array> --confirmed true --expected-rig-fingerprint <current>`.
   Each row is `{slotId,motionRefKey,autoMatched}`; use real candidate keys.
   Missing required clips, an old rig or changed profile are not an approved
   mapping. Never fabricate Idle or duplicate incompatible skeletons to pass.
7. `prepare-playable-export --json --asset <Asset Path>` is a local preparation,
   not a completed export. CLI `export-playable-character --asset <Asset Path>`
   prepares and confirms delivery in one interactive process, using the same
   explicit-approval rules as other Engine writes. In Workbench, prepare the character delivery, show
   its Engine pin, paths, hashes and effect, then let the user confirm or reject
   that exact operation. Its five-minute, process-local handle is single-use;
   a new CLI process cannot reuse it. A `pending_host` response is not success.
   Final delivery merges compatible clips, uses the official SDK importer and
   reports actual Scene/AnimationClip GUIDs and source indexes. Adopting an
   existing Engine model is separate from adopting a new working character and
   requires explicit clip-slot choices and ownership review. CLI
   `adopt-playable-character --asset <Asset Path> --model-path <game-relative GLB>
   --slot-mappings <JSON array> --confirmed true` still requires the interactive
   Engine-write confirmation; the mapping flag does not authorize the write.
   Each adoption row selects exactly one `clipName` or `sourceClipIndex` with
   its `slotId`. Inspect `engine-import-status --json --asset <Asset Path>`
   afterward; a receipt alone does not prove runtime playback.
   When the provider's complete motion GLB has its own different skeleton,
   do not force it into the preserved rig. For an explicitly reviewed
   single-action character, configure only that required slot, with
   `rootMotion: "preserve"`, and confirm its real candidate mapping against
   the current rig fingerprint. Pass `--self-contained-motion-ref <key>` to
   preparation and interactive `export-playable-character`. This opt-in copies
   the exact successful motion Job's complete model/skin/clip bytes and checks
   its source, rig Job, output hash and current registration. It supplies no
   additional Idle, does not retarget or change the preserved rig, and leaves
   the game default profile unchanged. Engine import still needs fresh write
   confirmation; actual scene integration and playback remain separate.
   Engine 0.3.3 may reject otherwise valid provider GLBs with duplicate image
   names. Do not edit original outputs or patch the SDK. Preparation stops
   before writing; explicitly review `--normalize-texture-names true` with the
   complete-motion reference to create a names-only derivative. Its report binds
   original/derived/BIN hashes, real PBR roles, SDK pin and changed image names
   to the new confirmation. Only name tokens change; geometry, textures, skin,
   animation and all other JSON tokens stay intact. Ambiguous roles, mixed
   sRGB/linear use or other output-key conflicts are blocked. A failed import's
   old approval cannot authorize this derivative; obtain a fresh same-session
   Engine-write approval and verify runtime playback separately.
8. A successful import still requires runtime consumption and visual review.
   The installed `@forgeax/game/gen3d/character-playback` entry exports
   `installCharacterPlayback`; its typed port binds the host's imported scene
   targets to the official `AnimationPlayer`. The game host supplies loaded
   clip handles and calls `afterAnimationFrame()` after animation updates.
   Do not generate old SDK GUIDs, copy Studio internals or change Engine pins.
   `requires-runtime-binding` means the game has not yet consumed the export.

## Local library, configuration and evidence

- `assets --json --slot characters --query <text>` filters
  the local library. Omitting a filter preserves the complete list; unreadable
  records remain visible as errors rather than disappearing from the inventory.
- `preview --json --asset <Asset Path>` or `preview --json --job <Job ID>`
  reads an already registered image witness; it does not generate or render.
  `render-preview --json --asset <Asset Path> --out <absolute PNG path>
  --size 512 --style shaded` renders locally through the owned browser. Use
  `--style clay` for geometry inspection. A requested `--angles` value still
  produces one image, with `renderedViews: 1`; never promise a contact sheet.
- Standalone `transfer --kind image|model|video --file <absolute path>
  --backend gateway|cos` and the fixed-kind `upload-image`, `upload-model`,
  `upload-video` aliases use a fresh interactive transfer confirmation. A
  `--json` preparation returns `pending_host` without uploading. Explicit
  `mock-generate --name <name> --prompt <text> --prompt-category character
  --pbr true --polycount 30000 --slot characters` is a local simulation and
  also has a confirmation gate. Its output must never be presented as a
  provider-generated character or automatic missing-credential fallback.
  Read `transfer-status`, recover with `transfer-resume` / `transfer-attach`,
  or resume an explicit mock with `mock-resume`, using `--job <Job ID>`.
  Unknown acceptance is recover-only: retry never authorizes a blind upload.
  `transfer-retry --job <Job ID>` may prepare a new attempt only when a
  persisted, explicit gateway non-admission witness exists. It needs fresh
  named confirmation, preserves the original failed Job and links the new
  attempt to it. An HTTP status alone (including 429) is not that witness.
  `cancel --json --job <Job ID>` records a local cancellation request and can
  signal a wait owned by this process; it does not cancel a remote provider
  task or prove that a different process has stopped.
- `inspect-asset --json --asset <Asset Path>` measures actual GLB structure and
  the legacy `hero-character` budget: 30,000 triangles, 2048 maximum texture
  edge and two materials. `--resource-path` selects a registered GLB dependency.
  Report unmeasurable textures as unknown, not a pass.
- `score-quality` stores measured and explicitly manual dimensions. Legacy
  client `objective` scores are unverified manual input; AI visual scoring is
  unsupported. Never substitute a fixed or invented AI score.
- `rename-asset --json --asset <Asset Path> --label <label>` changes display
  metadata, not identity; literal `null` clears it. `delete-asset` uses recoverable
  trash and respects shared dependencies and independently exported files;
  report the tombstone and use `restore-asset --json --tombstone <path>` to recover.
- `export-bundle --json --asset <Asset Path> --out <absolute ZIP path>` exports
  verified registered files with a hash manifest. Workbench downloads the same
  safe bundle. Missing or changed dependencies fail; raw credentials, private
  sidecars and signed remote URLs do not belong in the ZIP.
- `migration-dry-run --json --source-project <absolute path>` is read-only.
  Review every conflict and incomplete recovery witness before
  `migration-execute --json --source-project <same path> --expected-plan-hash <hash>`.
  Keep the old source unchanged. Old in-memory `gen3d-N` task IDs without a
  durable mapping are not recoverable and do not authorize re-submission.
- `config-status --json` returns safe configured/source status, not secrets.
  Workbench can explicitly save complete credential pairs. CLI `config-set
  --json --from-environment gateway|cos` and `config-import --json
  --source <explicit private file>` use the same host-neutral store. Never print
  keys or put them in command arguments. Temporary COS credentials remain
  environment-only. Missing configuration must not trigger automatic mock or
  direct-provider fallback.
- `job_output` is a durable local read with `wait=false`, not a second
  polling/session system. Retired provider aliases are not current production
  options; keep historical Job identities intact.
- Single-image local preview, Scout/Three.js, authored protocol fixtures,
  mock gateway, real provider outputs and Engine-visible animation are separate
  evidence classes. Preview's legacy `angles` argument is not evidence of a
  multi-view contact sheet. A real fee-bearing service check needs fresh scope,
  route, operation-count and cost approval; an earlier zero-cost mock approval
  does not carry over.
