@mcptoolshop/style-dataset-lab 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +108 -15
- package/CODE_OF_CONDUCT.md +9 -0
- package/CONTRIBUTING.md +71 -0
- package/README.es.md +99 -8
- package/README.fr.md +100 -9
- package/README.hi.md +102 -9
- package/README.it.md +99 -8
- package/README.ja.md +100 -9
- package/README.md +64 -1
- package/README.pt-BR.md +99 -8
- package/README.zh.md +100 -9
- package/SECURITY.md +6 -5
- package/bin/sdlab.js +289 -62
- package/lib/adapters/comfyui-runner.js +11 -15
- package/lib/adapters/diffusers-lora.js +7 -2
- package/lib/adapters/generic-image-caption.js +6 -1
- package/lib/args.js +200 -13
- package/lib/batch-compiler.js +7 -3
- package/lib/batch-runs.js +162 -31
- package/lib/batch-sheet-render.js +5 -2
- package/lib/brief-compiler.js +38 -11
- package/lib/card.js +11 -4
- package/lib/comfyui-output.js +70 -0
- package/lib/comfyui.js +100 -6
- package/lib/config.js +68 -3
- package/lib/deprecation.js +1 -1
- package/lib/eval-pack.js +94 -4
- package/lib/eval-runs.js +42 -3
- package/lib/export.js +144 -34
- package/lib/implementation-packs.js +15 -1
- package/lib/log.js +41 -4
- package/lib/paths.js +41 -3
- package/lib/refine-briefs.js +16 -9
- package/lib/reingest-selected.js +14 -3
- package/lib/reingest.js +15 -1
- package/lib/run-summary.js +3 -2
- package/lib/runtime-runs.js +59 -9
- package/lib/selections.js +54 -2
- package/lib/snapshot.js +100 -7
- package/lib/split.js +175 -17
- package/lib/training-adapters.js +79 -0
- package/lib/training-manifests.js +17 -3
- package/lib/training-packages.js +29 -28
- package/lib/training-profiles.js +10 -0
- package/package.json +27 -3
- package/scripts/batch-generate.js +72 -20
- package/scripts/batch-sheet.js +3 -3
- package/scripts/batch-show.js +3 -3
- package/scripts/brief-compile.js +8 -8
- package/scripts/brief-show.js +4 -3
- package/scripts/canon-bind.js +7 -9
- package/scripts/card.js +22 -25
- package/scripts/compare.js +38 -33
- package/scripts/critique-show.js +3 -3
- package/scripts/critique.js +3 -3
- package/scripts/curate.js +91 -46
- package/scripts/doctor.js +3 -5
- package/scripts/eligibility.js +17 -14
- package/scripts/eval-pack.js +13 -11
- package/scripts/eval-run.js +30 -29
- package/scripts/export.js +27 -31
- package/scripts/generate-controlnet.js +31 -17
- package/scripts/generate-identity.js +37 -20
- package/scripts/generate-ipadapter.js +22 -16
- package/scripts/generate.js +96 -29
- package/scripts/implementation-pack.js +19 -14
- package/scripts/init.js +115 -17
- package/scripts/painterly.js +8 -10
- package/scripts/refine.js +3 -3
- package/scripts/reingest-selected.js +3 -3
- package/scripts/reingest.js +33 -20
- package/scripts/run-generate.js +4 -4
- package/scripts/run-list.js +3 -3
- package/scripts/run-show.js +3 -3
- package/scripts/select.js +5 -4
- package/scripts/selection-show.js +3 -3
- package/scripts/snapshot.js +22 -24
- package/scripts/split.js +26 -31
- package/scripts/training-manifest.js +29 -24
- package/scripts/training-package.js +24 -20
- package/scripts/training-profile.js +13 -8
- package/scripts/workflow-list.js +2 -2
- package/scripts/workflow-show.js +4 -3
- package/templates/domains/architecture/inputs/prompts/example-wave.json +32 -0
- package/templates/domains/architecture/terminology.json +10 -8
- package/templates/domains/character-design/inputs/prompts/example-wave.json +32 -0
- package/templates/domains/character-design/project.json +4 -2
- package/templates/domains/creature-design/inputs/prompts/example-wave.json +32 -0
- package/templates/domains/creature-design/project.json +4 -2
- package/templates/domains/creature-design/terminology.json +1 -0
- package/templates/domains/game-art/inputs/prompts/example-wave.json +37 -0
- package/templates/domains/game-art/project.json +4 -2
- package/templates/domains/vehicle-mech/inputs/prompts/example-wave.json +37 -0
- package/templates/domains/vehicle-mech/project.json +4 -2
- package/scripts/bulk-curate-wave2-5.js +0 -138
- package/scripts/bulk-curate-waves11-18.js +0 -413
- package/scripts/curate-wave25.js +0 -209
- package/scripts/migrate-records.js +0 -141
- package/templates/inputs/prompts/example-wave.json +0 -27
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"wave": "wave1",
|
|
3
|
+
"description": "Architecture — first wave. Subject IDs match this domain's lane id_patterns (ext_, int_, street_) so `sdlab generate` will route each candidate into the correct lane instead of default_lane.",
|
|
4
|
+
"defaults": {
|
|
5
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
6
|
+
"lora": { "name": "classipeintxl_v21.safetensors", "weight": 1.0 },
|
|
7
|
+
"width": 1024,
|
|
8
|
+
"height": 1024,
|
|
9
|
+
"steps": 8,
|
|
10
|
+
"cfg": 2.0,
|
|
11
|
+
"sampler": "dpmpp_sde",
|
|
12
|
+
"scheduler": "karras",
|
|
13
|
+
"negative": "photorealistic, photograph, 3d render, smooth CG, sharp photo detail"
|
|
14
|
+
},
|
|
15
|
+
"subjects": [
|
|
16
|
+
{
|
|
17
|
+
"id": "ext_landmark",
|
|
18
|
+
"variations": 2,
|
|
19
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR BUILDING — facade, elevation, architectural massing], painterly concept art, canvas grain"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "int_hall",
|
|
23
|
+
"variations": 2,
|
|
24
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR INTERIOR — hall, chamber, spatial atmosphere], painterly concept art, canvas grain"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "street_district",
|
|
28
|
+
"variations": 2,
|
|
29
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR STREETSCAPE — street-level view, urban fabric, district overview], painterly concept art, canvas grain"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
"null_faction_patterns": [],
|
|
9
9
|
"id_fallbacks": {},
|
|
10
10
|
"faction_context": {},
|
|
11
|
-
"training_profiles":
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
"training_profiles": [
|
|
12
|
+
{
|
|
13
|
+
"profile_id": "architecture-style",
|
|
14
|
+
"intended_use": "Architectural style LoRA for consistent worldbuilding",
|
|
15
|
+
"eligible_lanes": ["exterior", "interior", "streetscape"],
|
|
16
|
+
"minimum_review_threshold": 0.7,
|
|
17
|
+
"excluded_content": ["rejected"],
|
|
18
|
+
"export_format": "trl"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
19
21
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"wave": "wave1",
|
|
3
|
+
"description": "Character design — first wave. Subject IDs match this domain's lane id_patterns (portrait_, full_, expr_) so `sdlab generate` will route each candidate into the correct lane instead of default_lane.",
|
|
4
|
+
"defaults": {
|
|
5
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
6
|
+
"lora": { "name": "classipeintxl_v21.safetensors", "weight": 1.0 },
|
|
7
|
+
"width": 1024,
|
|
8
|
+
"height": 1024,
|
|
9
|
+
"steps": 8,
|
|
10
|
+
"cfg": 2.0,
|
|
11
|
+
"sampler": "dpmpp_sde",
|
|
12
|
+
"scheduler": "karras",
|
|
13
|
+
"negative": "photorealistic, photograph, 3d render, smooth CG, sharp photo detail"
|
|
14
|
+
},
|
|
15
|
+
"subjects": [
|
|
16
|
+
{
|
|
17
|
+
"id": "portrait_hero",
|
|
18
|
+
"variations": 2,
|
|
19
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR HERO — head and shoulders, face detail, expression], painterly concept art, canvas grain"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "full_body_hero",
|
|
23
|
+
"variations": 2,
|
|
24
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR HERO — full figure standing pose, costume, silhouette], painterly concept art, canvas grain"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "expr_hero_sheet",
|
|
28
|
+
"variations": 2,
|
|
29
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR HERO — emotion range sheet, consistent face across multiple expressions], painterly concept art, canvas grain"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
"domain": "character-design",
|
|
5
5
|
"version": "0.1.0",
|
|
6
6
|
"defaults": {
|
|
7
|
-
"checkpoint": "",
|
|
8
|
-
"loras": [
|
|
7
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
8
|
+
"loras": [
|
|
9
|
+
{ "name": "classipeintxl_v21.safetensors", "weight": 1.0 }
|
|
10
|
+
],
|
|
9
11
|
"width": 1024,
|
|
10
12
|
"height": 1024,
|
|
11
13
|
"steps": 8,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"wave": "wave1",
|
|
3
|
+
"description": "Creature design — first wave. Subject IDs match this domain's lane id_patterns (concept_, ortho_, action_) so `sdlab generate` will route each candidate into the correct lane instead of default_lane.",
|
|
4
|
+
"defaults": {
|
|
5
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
6
|
+
"lora": { "name": "classipeintxl_v21.safetensors", "weight": 1.0 },
|
|
7
|
+
"width": 1024,
|
|
8
|
+
"height": 1024,
|
|
9
|
+
"steps": 8,
|
|
10
|
+
"cfg": 2.0,
|
|
11
|
+
"sampler": "dpmpp_sde",
|
|
12
|
+
"scheduler": "karras",
|
|
13
|
+
"negative": "photorealistic, photograph, 3d render, smooth CG, sharp photo detail"
|
|
14
|
+
},
|
|
15
|
+
"subjects": [
|
|
16
|
+
{
|
|
17
|
+
"id": "concept_alpha",
|
|
18
|
+
"variations": 2,
|
|
19
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR CREATURE — initial concept, ideation exploration], painterly concept art, canvas grain"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "ortho_alpha",
|
|
23
|
+
"variations": 2,
|
|
24
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR CREATURE — turnaround model sheet, orthographic views for modelers], painterly concept art, canvas grain"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "action_alpha",
|
|
28
|
+
"variations": 2,
|
|
29
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR CREATURE — attack stance, locomotion study, movement key], painterly concept art, canvas grain"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
"version": "0.1.0",
|
|
6
6
|
"description": "Creature concept art — fantasy creatures, alien species, monsters, wildlife, and mythological beings.",
|
|
7
7
|
"defaults": {
|
|
8
|
-
"checkpoint": "",
|
|
9
|
-
"loras": [
|
|
8
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
9
|
+
"loras": [
|
|
10
|
+
{ "name": "classipeintxl_v21.safetensors", "weight": 1.0 }
|
|
11
|
+
],
|
|
10
12
|
"width": 1024,
|
|
11
13
|
"height": 1024,
|
|
12
14
|
"steps": 8,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"wave": "wave1",
|
|
3
|
+
"description": "Game art — first wave. Subject IDs match this domain's lane id_patterns (char_, env_, prop_, ship_) so `sdlab generate` will route each candidate into the correct lane instead of default_lane.",
|
|
4
|
+
"defaults": {
|
|
5
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
6
|
+
"lora": { "name": "classipeintxl_v21.safetensors", "weight": 1.0 },
|
|
7
|
+
"width": 1024,
|
|
8
|
+
"height": 1024,
|
|
9
|
+
"steps": 8,
|
|
10
|
+
"cfg": 2.0,
|
|
11
|
+
"sampler": "dpmpp_sde",
|
|
12
|
+
"scheduler": "karras",
|
|
13
|
+
"negative": "photorealistic, photograph, 3d render, smooth CG, sharp photo detail"
|
|
14
|
+
},
|
|
15
|
+
"subjects": [
|
|
16
|
+
{
|
|
17
|
+
"id": "char_hero",
|
|
18
|
+
"variations": 2,
|
|
19
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR CHARACTER — costume, faction identity, personal gear], painterly concept art, canvas grain"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "env_town",
|
|
23
|
+
"variations": 2,
|
|
24
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR ENVIRONMENT — town, dungeon, overworld location], painterly concept art, canvas grain"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "prop_key",
|
|
28
|
+
"variations": 2,
|
|
29
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR PROP — quest item, treasure, story-carrying object], painterly concept art, canvas grain"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "ship_flagship",
|
|
33
|
+
"variations": 2,
|
|
34
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR SHIP OR VEHICLE — exterior view, faction silhouette], painterly concept art, canvas grain"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
"domain": "game-art",
|
|
5
5
|
"version": "0.1.0",
|
|
6
6
|
"defaults": {
|
|
7
|
-
"checkpoint": "",
|
|
8
|
-
"loras": [
|
|
7
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
8
|
+
"loras": [
|
|
9
|
+
{ "name": "classipeintxl_v21.safetensors", "weight": 1.0 }
|
|
10
|
+
],
|
|
9
11
|
"width": 1024,
|
|
10
12
|
"height": 1024,
|
|
11
13
|
"steps": 8,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"wave": "wave1",
|
|
3
|
+
"description": "Vehicle / mech — first wave. Subject IDs match this domain's lane id_patterns (ext_, cockpit_, component_, schematic_) so `sdlab generate` will route each candidate into the correct lane instead of default_lane.",
|
|
4
|
+
"defaults": {
|
|
5
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
6
|
+
"lora": { "name": "classipeintxl_v21.safetensors", "weight": 1.0 },
|
|
7
|
+
"width": 1024,
|
|
8
|
+
"height": 1024,
|
|
9
|
+
"steps": 8,
|
|
10
|
+
"cfg": 2.0,
|
|
11
|
+
"sampler": "dpmpp_sde",
|
|
12
|
+
"scheduler": "karras",
|
|
13
|
+
"negative": "photorealistic, photograph, 3d render, smooth CG, sharp photo detail"
|
|
14
|
+
},
|
|
15
|
+
"subjects": [
|
|
16
|
+
{
|
|
17
|
+
"id": "ext_flagship",
|
|
18
|
+
"variations": 2,
|
|
19
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR VEHICLE — hull design, body panels, overall form language], painterly concept art, canvas grain"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "cockpit_flagship",
|
|
23
|
+
"variations": 2,
|
|
24
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR COCKPIT — bridge layout, cabin instruments, pilot seating], painterly concept art, canvas grain"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "component_engine",
|
|
28
|
+
"variations": 2,
|
|
29
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE A COMPONENT — engine, weapon, thruster, subsystem detail], painterly concept art, canvas grain"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "schematic_overview",
|
|
33
|
+
"variations": 2,
|
|
34
|
+
"prompt": "oil painting, visible brushstrokes, [DESCRIBE YOUR SCHEMATIC — technical diagram, orthographic breakdown, cross-section], painterly concept art, canvas grain"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
"domain": "vehicle-mech",
|
|
5
5
|
"version": "0.1.0",
|
|
6
6
|
"defaults": {
|
|
7
|
-
"checkpoint": "",
|
|
8
|
-
"loras": [
|
|
7
|
+
"checkpoint": "dreamshaperXL_v21TurboDPMSDE.safetensors",
|
|
8
|
+
"loras": [
|
|
9
|
+
{ "name": "classipeintxl_v21.safetensors", "weight": 1.0 }
|
|
10
|
+
],
|
|
9
11
|
"width": 1024,
|
|
10
12
|
"height": 1024,
|
|
11
13
|
"steps": 8,
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Bulk curation for waves 2-5.
|
|
5
|
-
* Applies rules-based initial curation, then individual overrides.
|
|
6
|
-
* Must still visually verify — this is a first pass, not final judgment.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { readFile, writeFile, rename, readdir, mkdir } from "node:fs/promises";
|
|
10
|
-
import { join } from "node:path";
|
|
11
|
-
|
|
12
|
-
const REPO_ROOT = new URL("..", import.meta.url).pathname.replace(/^\/([A-Z]:)/, "$1");
|
|
13
|
-
const GAME = process.argv.find((a, i) => process.argv[i - 1] === '--game') || 'star-freight';
|
|
14
|
-
const GAME_ROOT = join(REPO_ROOT, 'projects', GAME);
|
|
15
|
-
|
|
16
|
-
const DEFAULT_APPROVED_SCORES = {
|
|
17
|
-
silhouette_clarity: 0.8, palette_adherence: 0.8, material_fidelity: 0.8,
|
|
18
|
-
faction_read: 0.8, wear_level: 0.8, style_consistency: 0.7,
|
|
19
|
-
clothing_logic: 0.8, composition: 0.8,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const REJECT_EXPLANATIONS = {
|
|
23
|
-
"REJECT2_fantasy_knight": { explanation: "Full medieval plate armor, heraldic tabard, broadsword and shield. Fantasy not sci-fi. Violates every art pillar.", failures: ["generic_scifi", "wrong_material"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.2, material_fidelity: 0.4, faction_read: 0.0, wear_level: 0.3, style_consistency: 0.4, clothing_logic: 0.1, composition: 0.8 } },
|
|
24
|
-
"REJECT2_cyberpunk_f": { explanation: "Neon hair, glowing circuit tattoos, shiny PVC bodysuit, LED accessories. Cyberpunk nightclub not cargo bay. Violates COL-003, CLO-003.", failures: ["wrong_palette", "costume_not_clothes"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.1, material_fidelity: 0.3, faction_read: 0.0, wear_level: 0.1, style_consistency: 0.3, clothing_logic: 0.1, composition: 0.8 } },
|
|
25
|
-
"REJECT2_too_sexy_f": { explanation: "Skin-tight form-fitting uniform emphasizing figure, styled hair, makeup, high heels. Cosplay not clothing. Violates CLO-003, MAT-002.", failures: ["costume_not_clothes", "too_clean"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.5, material_fidelity: 0.3, faction_read: 0.3, wear_level: 0.1, style_consistency: 0.4, clothing_logic: 0.2, composition: 0.8 } },
|
|
26
|
-
"REJECT2_warhammer_m": { explanation: "Bulky powered exoskeleton with imperial eagles, purity seals, gothic elements, chainsaw sword. Warhammer 40k power fantasy. Violates all five art pillars.", failures: ["generic_scifi", "too_heroic", "costume_not_clothes"], scores: { silhouette_clarity: 0.9, palette_adherence: 0.2, material_fidelity: 0.5, faction_read: 0.0, wear_level: 0.2, style_consistency: 0.4, clothing_logic: 0.1, composition: 0.8 } },
|
|
27
|
-
"REJECT3_veshan_cute": { explanation: "Cute baby reptilian with big round eyes, pastel skin, tiny adorable outfit. Mascot character not warrior culture. Violates faction identity completely.", failures: ["faction_unreadable", "costume_not_clothes"], scores: { silhouette_clarity: 0.7, palette_adherence: 0.2, material_fidelity: 0.3, faction_read: 0.1, wear_level: 0.1, style_consistency: 0.3, clothing_logic: 0.2, composition: 0.8 } },
|
|
28
|
-
"REJECT3_veshan_robot": { explanation: "Reptilian in sleek chrome powered armor covering every scale, glowing visor, jet thrusters. Mecha pilot not Veshan warrior. No forge marks, no imperfections. Violates MAT-001, CLO-002.", failures: ["generic_scifi", "wrong_material", "too_clean"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.3, material_fidelity: 0.2, faction_read: 0.2, wear_level: 0.1, style_consistency: 0.5, clothing_logic: 0.2, composition: 0.8 } },
|
|
29
|
-
"REJECT3_generic_lizard": { explanation: "Generic lizard person in brown tunic. No crest ridge, no brow ridges, no tail, round eyes, smooth skin, human proportions. Human in lizard mask, not an alien species.", failures: ["faction_unreadable", "wrong_material"], scores: { silhouette_clarity: 0.7, palette_adherence: 0.4, material_fidelity: 0.3, faction_read: 0.1, wear_level: 0.5, style_consistency: 0.5, clothing_logic: 0.3, composition: 0.8 } },
|
|
30
|
-
"REJECT4_clean_pirate": { explanation: "Dashing pirate in pristine white shirt, embroidered vest, polished boots, jeweled rapier. Romance novel cover not lawless frontier. Violates MAT-002, CLO-003.", failures: ["too_clean", "costume_not_clothes"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.3, material_fidelity: 0.3, faction_read: 0.2, wear_level: 0.1, style_consistency: 0.4, clothing_logic: 0.2, composition: 0.8 } },
|
|
31
|
-
"REJECT4_matching_gang": { explanation: "Perfectly matching black tactical gear — same brand, same condition, all pristine. Video game loadout not Sable Reach. Nothing mismatched, nothing salvaged, nothing stolen.", failures: ["too_clean", "generic_scifi"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.4, material_fidelity: 0.5, faction_read: 0.1, wear_level: 0.2, style_consistency: 0.5, clothing_logic: 0.2, composition: 0.8 } },
|
|
32
|
-
"REJECT4_space_cowboy": { explanation: "Old west cowboy outfit in space — chaps, Stetson, plaid shirt, spurs. Genre costume at a sci-fi convention, not lived-in sci-fi. Violates CLO-003.", failures: ["costume_not_clothes", "faction_unreadable"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.3, material_fidelity: 0.4, faction_read: 0.0, wear_level: 0.5, style_consistency: 0.3, clothing_logic: 0.1, composition: 0.8 } },
|
|
33
|
-
"REJECT5_all_factions_salad": { explanation: "Designer outfit smoothly blending all faction aesthetics into one harmonious garment. Nothing is torn, stolen, or improvised. Violates every faction boundary rule.", failures: ["faction_unreadable", "too_clean"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.3, material_fidelity: 0.5, faction_read: 0.1, wear_level: 0.3, style_consistency: 0.5, clothing_logic: 0.2, composition: 0.8 } },
|
|
34
|
-
"REJECT5_no_faction_generic": { explanation: "Plain grey jumpsuit with zero cultural markers, no patches, no tools, no wear. Default human in default outfit. Nothing to learn from this.", failures: ["faction_unreadable"], scores: { silhouette_clarity: 0.7, palette_adherence: 0.4, material_fidelity: 0.3, faction_read: 0.0, wear_level: 0.3, style_consistency: 0.5, clothing_logic: 0.2, composition: 0.8 } },
|
|
35
|
-
"REJECT5_luxury_scifi": { explanation: "Tailored suit, gold watch, polished shoes, groomed hair. Corporate luxury executive. Never loaded cargo, never fixed a reactor. Not working-class space.", failures: ["too_clean", "costume_not_clothes"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.4, material_fidelity: 0.4, faction_read: 0.1, wear_level: 0.1, style_consistency: 0.5, clothing_logic: 0.2, composition: 0.8 } },
|
|
36
|
-
"REJECT6_fashion_model_f": { explanation: "Haute couture space-themed evening gown with crystals and high heels. Fashion runway not shipboard life. Violates every art pillar.", failures: ["costume_not_clothes", "too_clean"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.1, material_fidelity: 0.2, faction_read: 0.0, wear_level: 0.0, style_consistency: 0.3, clothing_logic: 0.0, composition: 0.8 } },
|
|
37
|
-
"REJECT6_steampunk_m": { explanation: "Victorian steampunk with top hat, brass goggles, gears and cogs, steam-powered prosthetic. Retro-futurism cosplay not lived-in sci-fi. Wrong aesthetic entirely.", failures: ["costume_not_clothes", "generic_scifi"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.3, material_fidelity: 0.4, faction_read: 0.0, wear_level: 0.4, style_consistency: 0.3, clothing_logic: 0.1, composition: 0.8 } },
|
|
38
|
-
"REJECT6_identical_twins": { explanation: "Two identical figures in matching pristine uniforms. Violates single character rule and too-clean rule. Looks like mannequins or clones.", failures: ["bad_composition", "too_clean"], scores: { silhouette_clarity: 0.5, palette_adherence: 0.6, material_fidelity: 0.5, faction_read: 0.5, wear_level: 0.1, style_consistency: 0.5, clothing_logic: 0.4, composition: 0.2 } },
|
|
39
|
-
"REJECT7_veshan_human_clothes": { explanation: "Veshan in Compact-style pressed uniform designed for human body. Fights against scale ridges and digitigrade legs. Wrong material vocabulary for species.", failures: ["wrong_material", "faction_unreadable"], scores: { silhouette_clarity: 0.7, palette_adherence: 0.5, material_fidelity: 0.2, faction_read: 0.2, wear_level: 0.6, style_consistency: 0.6, clothing_logic: 0.2, composition: 0.8 } },
|
|
40
|
-
"REJECT7_cute_dragon": { explanation: "Adorable small dragon with sparkly eyes, tiny wings, pink pastel scales, cute crown and cape with stars. Mascot toy not warrior civilization member.", failures: ["faction_unreadable", "costume_not_clothes"], scores: { silhouette_clarity: 0.7, palette_adherence: 0.1, material_fidelity: 0.2, faction_read: 0.0, wear_level: 0.1, style_consistency: 0.2, clothing_logic: 0.1, composition: 0.8 } },
|
|
41
|
-
"REJECT8_superhero_f": { explanation: "Glossy red and gold spandex bodysuit with cape, mask, power pose, stylized emblem. Superhero costume not clothing. Wrong genre entirely.", failures: ["costume_not_clothes", "generic_scifi"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.1, material_fidelity: 0.2, faction_read: 0.0, wear_level: 0.0, style_consistency: 0.2, clothing_logic: 0.0, composition: 0.7 } },
|
|
42
|
-
"REJECT8_zombified_m": { explanation: "Rotting grey skin, milky eyes, bloodied torn uniform. Horror zombie genre not lived-in sci-fi. Wrong genre.", failures: ["generic_scifi"], scores: { silhouette_clarity: 0.7, palette_adherence: 0.3, material_fidelity: 0.4, faction_read: 0.3, wear_level: 0.5, style_consistency: 0.3, clothing_logic: 0.3, composition: 0.7 } },
|
|
43
|
-
"REJECT9_invisible_m": { explanation: "Cloaking suit making the character transparent. Cannot judge style of something invisible. Science fiction special effect not costume.", failures: ["generic_scifi"], scores: { silhouette_clarity: 0.1, palette_adherence: 0.2, material_fidelity: 0.1, faction_read: 0.0, wear_level: 0.0, style_consistency: 0.3, clothing_logic: 0.1, composition: 0.5 } },
|
|
44
|
-
"REJECT9_alien_xenomorph": { explanation: "Biomechanical Xenomorph creature from the Alien franchise. No clothing, existing IP not original design. Wrong in every way.", failures: ["generic_scifi", "faction_unreadable"], scores: { silhouette_clarity: 0.8, palette_adherence: 0.2, material_fidelity: 0.3, faction_read: 0.0, wear_level: 0.0, style_consistency: 0.3, clothing_logic: 0.0, composition: 0.7 } },
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
async function main() {
|
|
48
|
-
const recordsDir = join(GAME_ROOT, "records");
|
|
49
|
-
const files = await readdir(recordsDir);
|
|
50
|
-
|
|
51
|
-
let approved = 0;
|
|
52
|
-
let rejected = 0;
|
|
53
|
-
let total = 0;
|
|
54
|
-
|
|
55
|
-
for (const file of files.filter(f => f.endsWith(".json")).sort()) {
|
|
56
|
-
const path = join(recordsDir, file);
|
|
57
|
-
const record = JSON.parse(await readFile(path, "utf-8"));
|
|
58
|
-
|
|
59
|
-
// Skip already curated
|
|
60
|
-
if (record.judgment) continue;
|
|
61
|
-
|
|
62
|
-
total++;
|
|
63
|
-
const id = record.id;
|
|
64
|
-
const baseId = id.replace(/_v[12]$/, "");
|
|
65
|
-
|
|
66
|
-
// Determine status
|
|
67
|
-
let status, explanation, failures = [], scores;
|
|
68
|
-
|
|
69
|
-
if (REJECT_EXPLANATIONS[baseId]) {
|
|
70
|
-
const rej = REJECT_EXPLANATIONS[baseId];
|
|
71
|
-
status = "rejected";
|
|
72
|
-
explanation = rej.explanation;
|
|
73
|
-
failures = rej.failures;
|
|
74
|
-
scores = rej.scores;
|
|
75
|
-
} else if (baseId.startsWith("BORDERLINE_")) {
|
|
76
|
-
status = "borderline";
|
|
77
|
-
explanation = `Almost on-style but fails in a subtle way that teaches nuance. See subject ID for specific issue.`;
|
|
78
|
-
scores = { silhouette_clarity: 0.7, palette_adherence: 0.65, material_fidelity: 0.65, faction_read: 0.6, wear_level: 0.6, style_consistency: 0.65, clothing_logic: 0.6, composition: 0.75 };
|
|
79
|
-
} else {
|
|
80
|
-
// Default approve with standard scores
|
|
81
|
-
status = "approved";
|
|
82
|
-
explanation = `On-style gritty space costume. Faction-appropriate material vocabulary and wear level. Reads as a working person in a spacefaring civilization.`;
|
|
83
|
-
scores = { ...DEFAULT_APPROVED_SCORES };
|
|
84
|
-
|
|
85
|
-
// Adjust explanation by faction prefix
|
|
86
|
-
if (id.startsWith("c2_")) {
|
|
87
|
-
explanation = `Compact faction crew. Regulation shipboard clothing with appropriate wear and institutional identity markers. Muted palette, functional design.`;
|
|
88
|
-
} else if (id.startsWith("v3_")) {
|
|
89
|
-
explanation = `Veshan faction. Forged material vocabulary with overlapping scales, dark bronze plate, leather underpadding. Martial culture expressed through gear.`;
|
|
90
|
-
scores.material_fidelity = 0.85;
|
|
91
|
-
} else if (id.startsWith("sr4_")) {
|
|
92
|
-
explanation = `Sable Reach outlaw. Salvaged, stolen, and improvised gear. Nothing matches, nothing is new, everything tells a survival story.`;
|
|
93
|
-
scores.faction_read = 0.85;
|
|
94
|
-
scores.wear_level = 0.9;
|
|
95
|
-
} else if (id.startsWith("cf_")) {
|
|
96
|
-
explanation = `Cross-faction comparison subject. Faction-appropriate costume for the specified role, useful for teaching same-role-different-faction visual discrimination.`;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Move image
|
|
101
|
-
const oldPath = join(GAME_ROOT, record.asset_path);
|
|
102
|
-
const newDir = `outputs/${status}`;
|
|
103
|
-
const newPath = `${newDir}/${id}.png`;
|
|
104
|
-
await mkdir(join(GAME_ROOT, newDir), { recursive: true });
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
await rename(oldPath, join(GAME_ROOT, newPath));
|
|
108
|
-
} catch {
|
|
109
|
-
console.log(` skip ${id} — image not found at ${record.asset_path}`);
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Update record
|
|
114
|
-
record.asset_path = newPath;
|
|
115
|
-
record.judgment = {
|
|
116
|
-
status,
|
|
117
|
-
reviewer: "bulk_curate_v1",
|
|
118
|
-
reviewed_at: new Date().toISOString(),
|
|
119
|
-
explanation,
|
|
120
|
-
criteria_scores: scores,
|
|
121
|
-
failure_modes: failures,
|
|
122
|
-
improvement_notes: null,
|
|
123
|
-
confidence: status === "rejected" ? 0.95 : 0.75, // bulk approvals get lower confidence
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
await writeFile(path, JSON.stringify(record, null, 2));
|
|
127
|
-
|
|
128
|
-
if (status === "approved") approved++;
|
|
129
|
-
else rejected++;
|
|
130
|
-
|
|
131
|
-
const icon = status === "approved" ? "\x1b[32m✓\x1b[0m" : "\x1b[31m✗\x1b[0m";
|
|
132
|
-
console.log(`${icon} ${id} → ${status}`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
console.log(`\n${total} curated: ${approved} approved, ${rejected} rejected`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
main().catch(console.error);
|