@mcptoolshop/style-dataset-lab 3.3.0 → 3.5.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 +60 -0
- package/README.es.md +117 -55
- package/README.fr.md +125 -65
- package/README.hi.md +117 -68
- package/README.it.md +119 -58
- package/README.ja.md +124 -74
- package/README.md +73 -7
- package/README.pt-BR.md +128 -63
- package/README.zh.md +116 -65
- package/bin/sdlab.js +100 -4
- package/lib/adapters/ai-toolkit.js +224 -35
- package/lib/adapters/comfyui-runner.js +79 -26
- package/lib/adapters/comfyui-workflows.js +94 -11
- package/lib/adapters/diffusers-lora.js +37 -5
- package/lib/adapters/generic-image-caption.js +43 -5
- package/lib/args.js +16 -1
- package/lib/asset-ingest.js +575 -0
- package/lib/asset-masks.js +323 -0
- package/lib/asset-source.js +1176 -0
- package/lib/batch-modes.js +29 -8
- package/lib/batch-runs.js +29 -1
- package/lib/batch-sheet-render.js +13 -3
- package/lib/brief-compiler.js +19 -0
- package/lib/candidate-sheet.js +327 -0
- package/lib/canon-author.js +350 -0
- package/lib/canon-build/build.js +146 -93
- package/lib/canon-review-gate.js +205 -0
- package/lib/captions.js +57 -0
- package/lib/card.js +74 -2
- package/lib/colab-launcher-guards.js +285 -0
- package/lib/comfyui.js +116 -18
- package/lib/config.js +116 -12
- package/lib/critique-engine.js +36 -2
- package/lib/eligibility.js +121 -9
- package/lib/eval-pack.js +14 -14
- package/lib/eval-runs.js +33 -0
- package/lib/export.js +122 -34
- package/lib/freeze-gate.js +16 -3
- package/lib/freeze-stamp.js +28 -3
- package/lib/generated-provenance.js +194 -6
- package/lib/implementation-packs.js +95 -17
- package/lib/ingest.js +396 -0
- package/lib/judgment-provenance.js +220 -0
- package/lib/lane1-render.js +668 -0
- package/lib/measure.js +422 -0
- package/lib/memory-store.js +663 -0
- package/lib/model-licences.js +305 -0
- package/lib/npy-meta.js +130 -0
- package/lib/paths.js +196 -7
- package/lib/png-meta.js +512 -0
- package/lib/records.js +54 -8
- package/lib/reingest-selected.js +113 -17
- package/lib/reingest.js +27 -3
- package/lib/run-manifest.js +159 -25
- package/lib/run-summary.js +12 -6
- package/lib/runtime-runs.js +45 -4
- package/lib/snapshot.js +114 -15
- package/lib/split.js +364 -48
- package/lib/train-runs.js +214 -0
- package/lib/training-manifests.js +114 -21
- package/lib/training-packages.js +147 -15
- package/lib/verifier.js +3 -0
- package/lib/verify-chain.js +367 -0
- package/lib/workflow-profiles.js +24 -3
- package/package.json +4 -3
- package/runtime/comfyui/txt2img-qwen.json +38 -0
- package/runtime/comfyui/txt2img-standard.json +21 -0
- package/scripts/_resume.js +62 -0
- package/scripts/_shared-args.js +44 -0
- package/scripts/asset-ingest.js +160 -0
- package/scripts/brief-compile.js +2 -1
- package/scripts/brief-show.js +2 -1
- package/scripts/canon-bind.js +2 -2
- package/scripts/canon-build.js +27 -20
- package/scripts/canon-draft.js +82 -0
- package/scripts/canon-drift.js +16 -7
- package/scripts/canon-freeze-status.js +14 -6
- package/scripts/canon-freeze.js +31 -11
- package/scripts/canon-unfreeze.js +17 -9
- package/scripts/card.js +2 -2
- package/scripts/colab/REAL_SERVICE_ASSUMPTIONS.md +14 -0
- package/scripts/colab/ai-toolkit-override-py315.txt +45 -0
- package/scripts/colab/colab_window.sh +587 -0
- package/scripts/colab/lane1_render.py +970 -0
- package/scripts/colab/launch_guards.py +564 -0
- package/scripts/colab/launch_lane1_stub.sh +309 -0
- package/scripts/colab/launch_lane3_stub.sh +366 -0
- package/scripts/colab/remote_runner.py +59 -0
- package/scripts/compare.js +2 -2
- package/scripts/critique.js +16 -1
- package/scripts/curate.js +2 -2
- package/scripts/doctor.js +182 -55
- package/scripts/eligibility.js +42 -2
- package/scripts/eval-pack.js +2 -2
- package/scripts/eval-run.js +2 -2
- package/scripts/export.js +2 -2
- package/scripts/generate-controlnet.js +45 -25
- package/scripts/generate-identity.js +53 -23
- package/scripts/generate-ipadapter.js +44 -23
- package/scripts/generate.js +86 -17
- package/scripts/implementation-pack.js +2 -2
- package/scripts/ingest.js +145 -0
- package/scripts/init.js +73 -13
- package/scripts/measure.js +170 -0
- package/scripts/measure_image.py +458 -0
- package/scripts/migrate-records.js +142 -0
- package/scripts/painterly-test.js +4 -3
- package/scripts/painterly.js +7 -3
- package/scripts/qwen_generate.py +138 -20
- package/scripts/reingest.js +2 -2
- package/scripts/sheet.js +142 -0
- package/scripts/snapshot.js +2 -2
- package/scripts/split.js +2 -2
- package/scripts/training-manifest.js +2 -2
- package/scripts/training-package.js +2 -2
- package/scripts/training-profile.js +2 -2
- package/scripts/verify.js +67 -0
- package/scripts/workflow-list.js +2 -1
- package/scripts/workflow-show.js +2 -1
|
@@ -16,6 +16,8 @@ import { writeFile, mkdir, symlink, copyFile } from 'node:fs/promises';
|
|
|
16
16
|
import { join, relative } from 'node:path';
|
|
17
17
|
import { existsSync } from 'node:fs';
|
|
18
18
|
import { groupRowsByPartition } from '../rows.js';
|
|
19
|
+
import { assertSafeAssetPath, assertSafeId } from '../export.js';
|
|
20
|
+
import { warn } from '../log.js';
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Build training package in diffusers LoRA format from canonical rows.
|
|
@@ -33,6 +35,11 @@ export async function buildPackage({ packageDir, rows, profile, manifest, config
|
|
|
33
35
|
const partitioned = groupRowsByPartition(rows || []);
|
|
34
36
|
|
|
35
37
|
let imageCount = 0;
|
|
38
|
+
// SDL-C5: per-row failure accounting (export.js DB-002 shape) — see
|
|
39
|
+
// generic-image-caption.js for the full rationale. A caught copy/symlink
|
|
40
|
+
// error must not silently drop the image, caption sidecar, AND metadata
|
|
41
|
+
// row together with zero logging.
|
|
42
|
+
const imagesFailed = [];
|
|
36
43
|
|
|
37
44
|
for (const [partition, partitionRows] of Object.entries(partitioned)) {
|
|
38
45
|
const datasetDir = join(packageDir, 'dataset', partition);
|
|
@@ -43,10 +50,21 @@ export async function buildPackage({ packageDir, rows, profile, manifest, config
|
|
|
43
50
|
const metadataRows = [];
|
|
44
51
|
|
|
45
52
|
for (const row of partitionRows) {
|
|
46
|
-
if (!row.asset_path)
|
|
53
|
+
if (!row.asset_path) {
|
|
54
|
+
imagesFailed.push({ record_id: row.entity_id, partition, reason: 'missing_asset_path' });
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
// SDL-H5 / SDL-H6: defense-in-depth — see generic-image-caption.js
|
|
59
|
+
// for the full rationale. Throws (hard fail) on traversal/unsafe id;
|
|
60
|
+
// that is a security boundary, not an operational hiccup.
|
|
61
|
+
assertSafeId(row.entity_id, `row.entity_id in diffusers-lora adapter (partition "${partition}")`);
|
|
62
|
+
const sourcePath = assertSafeAssetPath(row.asset_path, projectRoot, row.entity_id);
|
|
63
|
+
|
|
64
|
+
if (!existsSync(sourcePath)) {
|
|
65
|
+
imagesFailed.push({ record_id: row.entity_id, partition, reason: 'source_missing' });
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
50
68
|
|
|
51
69
|
const sourceBasename = row.asset_path.split(/[\\/]/).pop();
|
|
52
70
|
const extMatch = sourceBasename.match(/\.[^.]+$/);
|
|
@@ -62,7 +80,13 @@ export async function buildPackage({ packageDir, rows, profile, manifest, config
|
|
|
62
80
|
await symlink(relative(datasetDir, sourcePath), destPath);
|
|
63
81
|
}
|
|
64
82
|
imageCount++;
|
|
65
|
-
} catch {
|
|
83
|
+
} catch (err) {
|
|
84
|
+
imagesFailed.push({
|
|
85
|
+
record_id: row.entity_id,
|
|
86
|
+
partition,
|
|
87
|
+
reason: copy ? 'copy_failed' : 'link_failed',
|
|
88
|
+
detail: err.message,
|
|
89
|
+
});
|
|
66
90
|
continue;
|
|
67
91
|
}
|
|
68
92
|
|
|
@@ -77,7 +101,15 @@ export async function buildPackage({ packageDir, rows, profile, manifest, config
|
|
|
77
101
|
);
|
|
78
102
|
}
|
|
79
103
|
|
|
80
|
-
|
|
104
|
+
if (imagesFailed.length > 0) {
|
|
105
|
+
const sample = imagesFailed.slice(0, 10).map(f => `${f.record_id} (${f.reason})`);
|
|
106
|
+
warn(
|
|
107
|
+
`diffusers-lora adapter: ${imagesFailed.length} of ${imageCount + imagesFailed.length} rows failed to place` +
|
|
108
|
+
(imagesFailed.length > 10 ? ` — first 10: ${sample.join(', ')}, ...` : ` — ${sample.join(', ')}`),
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return { imageCount, imagesFailed };
|
|
81
113
|
}
|
|
82
114
|
|
|
83
115
|
function buildMetadataRow(row, partition, filename, stem) {
|
|
@@ -14,11 +14,20 @@ import { writeFile, mkdir, symlink, copyFile } from 'node:fs/promises';
|
|
|
14
14
|
import { join, relative } from 'node:path';
|
|
15
15
|
import { existsSync } from 'node:fs';
|
|
16
16
|
import { groupRowsByPartition } from '../rows.js';
|
|
17
|
+
import { assertSafeAssetPath, assertSafeId } from '../export.js';
|
|
18
|
+
import { warn } from '../log.js';
|
|
17
19
|
|
|
18
20
|
export async function buildPackage({ packageDir, rows, profile, manifest, config, projectRoot, copy }) {
|
|
19
21
|
const partitioned = groupRowsByPartition(rows || []);
|
|
20
22
|
|
|
21
23
|
let imageCount = 0;
|
|
24
|
+
// SDL-C5: per-row failure accounting (export.js DB-002 shape). The old
|
|
25
|
+
// bare `catch { continue; }` silently dropped the image, the caption
|
|
26
|
+
// sidecar, AND the metadata row together with no logging — on Windows
|
|
27
|
+
// without Developer Mode this fired on every row, so imageCount stayed
|
|
28
|
+
// 0 and the build still reported success. Every drop is now accounted
|
|
29
|
+
// for and returned to the caller.
|
|
30
|
+
const imagesFailed = [];
|
|
22
31
|
|
|
23
32
|
for (const [partition, partitionRows] of Object.entries(partitioned)) {
|
|
24
33
|
const datasetDir = join(packageDir, 'dataset', partition);
|
|
@@ -29,10 +38,25 @@ export async function buildPackage({ packageDir, rows, profile, manifest, config
|
|
|
29
38
|
const metadataRows = [];
|
|
30
39
|
|
|
31
40
|
for (const row of partitionRows) {
|
|
32
|
-
if (!row.asset_path)
|
|
41
|
+
if (!row.asset_path) {
|
|
42
|
+
imagesFailed.push({ record_id: row.entity_id, partition, reason: 'missing_asset_path' });
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
33
45
|
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
// SDL-H5 / SDL-H6: defense-in-depth. buildTrainingPackage validates
|
|
47
|
+
// every row before dispatching here, but this adapter is also
|
|
48
|
+
// unit-tested (and documented in lib/rows.js as a future direct
|
|
49
|
+
// canon-build target) independent of that caller, so the guard
|
|
50
|
+
// lives here too. A traversal / unsafe id is a security boundary,
|
|
51
|
+
// not an operational hiccup — it throws (hard fail) rather than
|
|
52
|
+
// joining the soft imagesFailed accounting below.
|
|
53
|
+
assertSafeId(row.entity_id, `row.entity_id in generic-image-caption adapter (partition "${partition}")`);
|
|
54
|
+
const sourcePath = assertSafeAssetPath(row.asset_path, projectRoot, row.entity_id);
|
|
55
|
+
|
|
56
|
+
if (!existsSync(sourcePath)) {
|
|
57
|
+
imagesFailed.push({ record_id: row.entity_id, partition, reason: 'source_missing' });
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
36
60
|
|
|
37
61
|
const sourceBasename = row.asset_path.split(/[\\/]/).pop();
|
|
38
62
|
const extMatch = sourceBasename.match(/\.[^.]+$/);
|
|
@@ -47,7 +71,13 @@ export async function buildPackage({ packageDir, rows, profile, manifest, config
|
|
|
47
71
|
await symlink(relative(datasetDir, sourcePath), destPath);
|
|
48
72
|
}
|
|
49
73
|
imageCount++;
|
|
50
|
-
} catch {
|
|
74
|
+
} catch (err) {
|
|
75
|
+
imagesFailed.push({
|
|
76
|
+
record_id: row.entity_id,
|
|
77
|
+
partition,
|
|
78
|
+
reason: copy ? 'copy_failed' : 'link_failed',
|
|
79
|
+
detail: err.message,
|
|
80
|
+
});
|
|
51
81
|
continue;
|
|
52
82
|
}
|
|
53
83
|
|
|
@@ -67,5 +97,13 @@ export async function buildPackage({ packageDir, rows, profile, manifest, config
|
|
|
67
97
|
);
|
|
68
98
|
}
|
|
69
99
|
|
|
70
|
-
|
|
100
|
+
if (imagesFailed.length > 0) {
|
|
101
|
+
const sample = imagesFailed.slice(0, 10).map(f => `${f.record_id} (${f.reason})`);
|
|
102
|
+
warn(
|
|
103
|
+
`generic-image-caption adapter: ${imagesFailed.length} of ${imageCount + imagesFailed.length} rows failed to place` +
|
|
104
|
+
(imagesFailed.length > 10 ? ` — first 10: ${sample.join(', ')}, ...` : ` — ${sample.join(', ')}`),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return { imageCount, imagesFailed };
|
|
71
109
|
}
|
package/lib/args.js
CHANGED
|
@@ -149,8 +149,23 @@ export function getProjectName(argv) {
|
|
|
149
149
|
for (let i = 0; i < argv.length; i++) {
|
|
150
150
|
const a = argv[i];
|
|
151
151
|
if (a === '--project' || a === '--game') {
|
|
152
|
+
const flagName = a === '--game' ? 'game' : 'project';
|
|
152
153
|
if (a === '--game') warnDeprecated('game', 'project');
|
|
153
|
-
|
|
154
|
+
const next = argv[i + 1];
|
|
155
|
+
// SDL-L1: mirror takeFlagValue's guard below — without it, a missing
|
|
156
|
+
// value silently swallowed the NEXT flag as the project name (e.g.
|
|
157
|
+
// `--project --dry-run` yielded the project name "--dry-run").
|
|
158
|
+
if (next === undefined) {
|
|
159
|
+
throw inputError('INPUT_MISSING_VALUE', `Flag --${flagName} requires a value.`);
|
|
160
|
+
}
|
|
161
|
+
if (next.startsWith('--')) {
|
|
162
|
+
throw inputError(
|
|
163
|
+
'INPUT_MISSING_VALUE',
|
|
164
|
+
`Flag --${flagName} is missing its value (got another flag: ${next}).`,
|
|
165
|
+
`Pass a value after --${flagName}.`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
explicit = next;
|
|
154
169
|
break;
|
|
155
170
|
}
|
|
156
171
|
if (a.startsWith('--project=')) { explicit = a.slice('--project='.length); break; }
|