From b2cc489fd4f1b284240accb924584043bff845fb Mon Sep 17 00:00:00 2001 From: Vito Date: Fri, 23 Oct 2026 01:38:36 -0700 Subject: [PATCH 1/2] feat(inspect): copy settings summary and local workflow roles (#286) * feat(inspect): copy settings summary in the full inspector The legacy metadata page's COPY ALL (LI-4) becomes "Copy settings summary" after the six facts of the shared full inspector, so the Images viewer, the recorded history's current file and Inspect all offer it; the Images side panel keeps the concept's footer. The text is the legacy copyAllData template with its placeholders, filled from what the inspector shows. A unit test runs the template read from web/metadata.html on the legacy parse of every parity PNG: 22 of 25 are byte-equal, and the other three differ only by the ZeroOut guard (#249) or facts the legacy parse missed. Copying follows the concept's prompt copy: the toast "Settings summary copied.", or the select-to-copy dialog (now titled per copy) without a clipboard. The concept comparisons map the button as D-NEW-1. * feat(inspect): local execution evidence and prompt tracing A browser port of the server's inspection resolver for one sampler (PR L3 Task 8, LI-1). local-resolver.mjs answers inspect_prompt_evidence's {prompts, resolution} for a local read's records: execution evidence (read_pair_execution and its per-node match), every traced strategy (encoders, strings, concatenations, PromptManager and its historical classes, passthrough, zeroed, selector branches, composites, guiders), the latent stage walk, the R1 overwritten-text guard and the inspection profile's visit, depth, text, path, built and scanned bounds, with the same reason codes and outcome lines. py-json.mjs reads the records as CPython's json.loads does (dict order and last-wins keys, int versus float, BigInt past 2^53, NaN) and measures and strips text as str does. Several sampler candidates, detailer stages and A1111 parameters raise LocalResolverGap until Task 9. Nothing is wired into Inspect yet. Python is the oracle: test_local_inspect_parity compares the port with the server on the parity corpus, 107 named record sets, every work bound at its edge and 600 seeded fuzzed graphs, and requires gaps to be exactly the Task 9 paths. Sixteen porting mutations each fail the suite. The Node unit test replays committed server answers, which the Python suite keeps current. * fix(inspect): a list or object workflow node type answers malformed The R1 overwritten-text check looked every UI workflow node's `type` up among the subgraph IDs. A `type` that is a JSON list or object raised TypeError there, so the inspect route answered 500 "Prompt inspection failed". Such a workflow is now malformed evidence: the resolution is unresolved with reason_code `malformed` and the inspector's own "Prompt evidence is malformed" line, never exception text. The browser port answers the same, and the parity corpus gains the list, object, nested-subgraph and skipped-ID shapes. * fix(inspect): a list or object graph class_type is never a preview output With several sampler candidates the inspector first drops stages whose outputs reach only previews. That pass looked each API graph node's `class_type` up in the preview class set, so a list or object `class_type` raised TypeError and the inspect route answered 500. Only a string names a class now; such a node is an ordinary terminal, as the rest of the resolver already treats it. * feat(inspect): local candidate selection matching the inspector The browser port of the inspection resolver now answers every record set the server does, so no path is left to the server any more: - several sampler candidates, with the identical-branch rule (#270): a compare grid whose branches all resolve to one pair (text and recipe) is resolved, any other mix is ambiguous; - stages whose outputs reach only previews are dropped first; - detailer stages are judged with the samplers in their image ancestry (multistage-differs, cycles, depth and the per-stage visit budgets), and a sampler that only feeds detailers is not a candidate of its own; - A1111 `parameters`, with Python's multiline anchors, `\s` and Unicode `\d`, the bare footer and Template trailers, counted in code points. The parity corpus gains the selection cases and a seeded fuzzer, and every inspection vector now gives the server's prompts, resolution and facts locally. 16 of 17 mutations are caught; the uncaught one (not flattening an ambiguous upstream stage) cannot change any answer. * feat(inspect): local prompts resolved like the server's A file chosen on the Inspect page now shows the prompts and resolution the server's inspector gives the same records: buildLocalPayload takes its roles from the local resolver instead of the interim open roles, so the legacy fill applies exactly where it does for Images. The resolver reads the server's own node table. The page fetches web/js/inspection-semantics.json once through the API client as it mounts, before any selection; the static route serves that one JSON file by exact path (every other JSON stays forbidden). A table that cannot be fetched answers "The inspector's node table is unavailable." as the server does, and a later selection asks again. The Copy settings summary deviation is numbered D117. * fix(inspect): skip a workflow node whose type is a list or object The overwritten-PromptManager walk now skips such a node, on the server and in the browser port, instead of marking the whole file malformed. A prompt that resolves still resolves; the other nodes still feed the check. * fix(inspect): one JSON depth cap for both browser parsers py-json.mjs and local-video.mjs now refuse past the same 1,000 nested arrays or objects, counting every container as CPython's scanner does. Boundary vectors at 999, 1,000 and 1,001 for a deep prompt and a deep workflow run through the Python oracle, and TESTING.md gives the measured per-version server limits and both divergence directions. * fix(inspect): realpath containment for the exact-path node table route inspection-semantics.json now goes through the same realpath check as every other static file, so a symlink out of web/ is refused. The forbidden-path test asserts exactly 403. * fix(inspect): abortable, stepped local reads with a busy state The wait for the node table now ends with the selection's signal. A local read resolves and projects in bounded steps with a turn of the event loop between them, and the inspector carries aria-busy while it loads. A budget test covers maximal 2 MiB graphs and checks the stepped read is byte-identical to one synchronous build. The D117 wrap rule now targets only the summary button, and TESTING.md scopes the restart line to PRs L1 and L2. * fix(inspect): record the two CPython-JSON emulations as a follow-up --- TESTING.md | 111 +- py/api/__init__.py | 21 +- tests/browser/full-inspector.spec.mjs | 7 +- tests/browser/inspect-concept.spec.mjs | 15 +- tests/browser/inspector-concept.spec.mjs | 26 +- tests/browser/workspace-history.spec.mjs | 17 + tests/browser/workspace-inspect.spec.mjs | 128 +- .../local-inspect/resolver-vectors.json | 1 + tests/js/support/local-inspect-oracle.mjs | 34 + tests/js/workspace-file-inspector.test.js | 148 ++ tests/js/workspace-local-inspection.test.js | 162 +- tests/js/workspace-local-resolver.test.js | 161 ++ tests/js/workspace-local-semantics.test.js | 43 + tests/js/workspace-local-session.test.js | 4 +- tests/js/workspace-toolbar.test.js | 4 + tests/local_resolver_cases.py | 1405 +++++++++++++++++ tests/local_resolver_selection_cases.py | 574 +++++++ tests/test_api_core.py | 46 + tests/test_api_prompt_inspector.py | 56 + tests/test_local_inspect_parity.py | 308 ++++ tools/vendor/frontend-coverage-baseline.json | 38 +- utils/prompt_inspector.py | 3 +- utils/prompt_pair_resolver.py | 14 +- web/js/workspace/file-inspector.mjs | 46 +- web/js/workspace/inspect.mjs | 3 + web/js/workspace/local-inspection.mjs | 58 +- web/js/workspace/local-parameters.mjs | 55 + web/js/workspace/local-resolver-stages.mjs | 174 ++ web/js/workspace/local-resolver-support.mjs | 255 +++ web/js/workspace/local-resolver.mjs | 772 +++++++++ web/js/workspace/local-semantics.mjs | 27 + web/js/workspace/local-video.mjs | 5 +- web/js/workspace/py-json.mjs | 249 +++ web/js/workspace/workspace-dialogs.mjs | 9 +- web/js/workspace/workspace.css | 2 + 35 files changed, 4923 insertions(+), 58 deletions(-) create mode 100644 tests/fixtures/local-inspect/resolver-vectors.json create mode 100644 tests/js/workspace-local-resolver.test.js create mode 100644 tests/js/workspace-local-semantics.test.js create mode 100644 tests/local_resolver_cases.py create mode 100644 tests/local_resolver_selection_cases.py create mode 100644 web/js/workspace/local-parameters.mjs create mode 100644 web/js/workspace/local-resolver-stages.mjs create mode 100644 web/js/workspace/local-resolver-support.mjs create mode 100644 web/js/workspace/local-resolver.mjs create mode 100644 web/js/workspace/local-semantics.mjs create mode 100644 web/js/workspace/py-json.mjs diff --git a/TESTING.md b/TESTING.md index e298629..3303d20 100644 --- a/TESTING.md +++ b/TESTING.md @@ -398,6 +398,13 @@ naming it, here and in a detailer's image ancestry; a latent that is not a link reaches its own sampler is `malformed`; running out of budget is `work-limit` or `depth-limit`, never single stage. Each sampler's walk runs once per resolution; selector branch runs share it and other candidates are charged its visit cost. +A UI workflow node whose `type` is a list or an object (read only for the overwritten +PromptManager check) is skipped like a non-object node, since it can be neither a +subgraph instance nor a PromptManager node, so a prompt that resolves still resolves +and the other nodes still feed the check; a list or object `class_type` is never a +preview output. Before #286 both raised and the inspect route answered 500 +(`test_unhashable_*` in `tests/test_api_prompt_inspector.py`, the `workflow-type-*` +golden cases on both sides). Text encoders: `single` encoders (the Qwen image encoders, `TextEncodeQwenImage21` slot 0 `prompt` and slot 1 `negative_prompt`, `KikoTextEncode`) read one string input unchanged. `parts-equal` encoders (CLIPTextEncodeSDXL, Flux, SD3) resolve when @@ -1581,7 +1588,43 @@ AVI/WMV preview only), chosen or dropped, previews inline. The heading's one act the shared viewer with the full inspector on a record read entirely in this browser (`web/js/workspace/inspect.mjs`, `local-session.mjs`, `local-inspection.mjs` and the L1 readers `png-metadata.js`, `local-video.mjs`, `local-projection.mjs`). Nothing is -uploaded, imported or stored. Only HTML and JS change, so no ComfyUI restart is needed. +uploaded, imported or stored. PRs L1 and L2 change only HTML and JS, so they need no +ComfyUI restart; PR L3 does (below). + +Local roles (#249 PR L3, decision LI-1): the prompts and resolution of a local record are +the server inspector's for the same records. `web/js/workspace/local-resolver.mjs` (with +`local-resolver-support.mjs`, `local-resolver-stages.mjs`, `local-parameters.mjs` and +`py-json.mjs`) ports `inspect_prompt_evidence` with `INSPECTION_PROFILE`: execution +evidence, graph tracing, every bound, several sampler candidates with the +identical-branch rule (#270), preview-only stages, detailer stages (multistage) and A1111 +`parameters`. It reads the server's own node table, `web/js/inspection-semantics.json`, +which the page fetches once through the API client as it mounts, before any selection +(`local-semantics.mjs`; `/prompt_manager/js/inspection-semantics.json` is the one JSON +file the static route serves, by exact path). A table that cannot be fetched answers +"The inspector's node table is unavailable." as the server does. The legacy fill in +`projectInspectionPayload` then applies to a local record exactly where it applies to the +Images answer for the same bytes. Python is the oracle: +`tests/test_local_inspect_parity.py` `LocalResolverParityTests` compares the local +evidence byte for byte with `inspect_prompt_evidence` for every parity PNG and inspection +vector (prompts, resolution and facts), the golden and selection record sets +(`tests/local_resolver_cases.py`, `tests/local_resolver_selection_cases.py`), every work +bound and 1,200 seeded fuzz cases; `tests/fixtures/local-inspect/resolver-vectors.json` +holds the committed answers the Node unit test reads. The browser spec `chooser shows the +Images roles and resolution for every parity PNG` compares the rail with Images for all +25 committed parity PNGs. The static route change and the resolver fixes (Python) need a +ComfyUI restart. + +Main thread (M4): the resolver runs on the page's thread, not a worker. On a desktop +(Node 26) `resolveLocalEvidence` on maximal 2 MiB graphs (a 19,990-sampler chain, 6,600 +independent samplers, a consumer-dense scan, a 100,000-node PromptManager workflow) took +130–455 ms; the server took 80–905 ms on the same inputs. `localFileAdapter.read` runs in +bounded steps (read, table, parse and resolve, project, fit) with a turn of the event +loop between them, every wait ends with the selection's signal (a stalled table request +included), and the inspector carries `aria-busy="true"` with "Loading file details…" +until the answer lands. `tests/js/workspace-local-inspection.test.js` pins a 2,500 ms +budget per step on maximal independent-sampler and stage-chain graphs, checks that the +stepped read answers byte for byte as one synchronous build, and that an abort at any +step ends the read. Bounds (the server's own budgets, ported by PR L1; see "Follow-up: local Inspect parity" under "Chronological Library history" for the known divergences): @@ -1600,7 +1643,8 @@ under "Chronological Library history" for the known divergences): Privacy, asserted by `local inspection makes no content request or storage write` and `local roles send exactly` in `tests/browser/workspace-inspect.spec.mjs`, and by the -managed-host spec below: no request carries the file's bytes, name or text (fetch, XHR, +managed-host spec below: the only static file Inspect reads is its node table, once per +page and before any selection; no request carries the file's bytes, name or text (fetch, XHR, beacon, WebSocket, EventSource); Inspect writes nothing to `localStorage`, `sessionStorage` or IndexedDB; only an explicit Send crosses the host bridge, and its payload carries neither the `blob:` URL nor the filename; no console message names the @@ -1672,6 +1716,29 @@ mapped differences"): Modified with no Path row and no Show in folder, and ends with "Local file; no saved library association was checked." and Download original. There is no Prompt history action and no category or tag chips. +- **D117** (Copy settings summary, LI-4): the legacy metadata + page's COPY ALL, consolidated into the shared full inspector (the viewer's + `#viewer-details`, so Images, the recorded history's current file and Inspect all have + it). The concept has no such action. One plain button "Copy settings summary" follows + the six facts (before "File & provenance"); the Images side panel keeps the concept's + footer and has none. Its text is the legacy `copyAllData` template, line for line: + `Checkpoint`, `Positive Prompt`, `Negative Prompt`, `Steps`, `CFG Scale`, `Sampler`, + `Seed`, with the legacy placeholders ("Unknown", "No prompt found", "No negative prompt + found"). The values are the ones the inspector shows: a confirmed prompt and a known + fact verbatim, anything else (an explicitly empty prompt included, as the legacy parse + treats '') the placeholder. Against the legacy page, for the same file, only these + differ: numbers keep the server's spelling ("8.0" where the legacy page wrote 8); a fact + the legacy parse could not read can be known; and a negative the #249 ZeroOut guard + zeroed reads "No negative prompt found" where the legacy parse read the positive's text + through the zero-out. `workspace-file-inspector.test.js` runs the template taken from + `web/metadata.html` itself on the legacy parse of every parity PNG: 22 of 25 are + byte-equal, f01b and f23 differ by the ZeroOut guard and f17 by facts the legacy parse + missed. Copying works as the concept's prompt copy: the toast "Settings summary + copied.", or, without a clipboard or when it is refused, the select-to-copy dialog + titled "Copy settings summary". `.ca-tools #viewer-details > div > button` wraps + (`white-space: normal`) in the narrow rail at 200% zoom, as D20's buttons do. The concept + comparisons add the button to the concept's viewer at runtime (a copy of its own plain + button) and to the Inspect rail's section order. The chooser keeps naming the chosen file, as the concept's does: it is cleared as the picker opens (so choosing the same file again is a new selection), not after `change`, @@ -1685,9 +1752,8 @@ Legacy floor (`web/metadata.html`), dispositions: - Full text (the old "Show more"): the prompt blocks show the whole text. - Raw workflow view and Download workflow JSON: kept, in "Workflow & raw metadata". - Copy all summary and filename copy (LI-4): the filename is selectable text in the rail - and Download original saves the file under its name. The ruled "Copy settings summary" - button after the six facts of the shared full inspector is not part of PR L2; until it - lands, the legacy page keeps COPY ALL and stays reachable from Overview. + and Download original saves the file under its name. COPY ALL is the shared full + inspector's "Copy settings summary" (D117), with the legacy text. - Fully browser-local reading: kept and asserted (privacy above). - Case-variant keys `Workflow|comfy|ComfyUI|Prompt|Parameters` (LI-5): a separate backend issue; Inspect follows the server's readers, so the two never disagree. @@ -2280,12 +2346,41 @@ skip without ffmpeg). The remaining known divergences, checked against ffprobe 9 `unreadable`); ffprobe reads such files. - An EBML DocType other than `matroska`/`webm` is an invalid container locally; ffmpeg only warns and reads it. -- Envelope JSON deeper than 1,000 levels is refused locally as Python's default - recursion limit refuses it; the server's real limit depends on the interpreter and - call stack. A duplicate key in an object enclosing a nest deeper than the running +- Deep JSON (local roles, PR L3, and video envelopes): both browser CPython-JSON + parsers (`py-json.mjs`, `local-video.mjs`) share one cap, `JSON_MAX_DEPTH` = 1,000 + nested arrays or objects (each counts, an empty one too); past it a record is invalid + JSON locally. The server's `json.loads` raises RecursionError at a limit that depends + on the Python, measured on Linux x86-64: 993 levels from a bare script on 3.10 and + 3.11 (the 1,000 recursion limit minus the caller's frames, so about 990 inside the + server), 9,997 on 3.12 and 9,998 on 3.13 (the C recursion counter; lower on Windows + builds), and about 52,150 on 3.14 (stack-based, varies with the thread's stack). + The record kinds answer: a deep `prompt` graph (or `comfyassets_prompt_pairs` + envelope) is malformed; a deep `workflow` is ignored, so the overwritten PromptManager + check (R1) does not run and a prompt can resolve; a deep video `comment` or + `description` envelope makes the file unreadable on both sides (the server's + RecursionError reaches `read_inspection_file`). That gives two directions: + - 3.10/3.11, between the server's limit and 1,000: the server refuses and the local + page reads, so a deep prompt resolves locally while the server says malformed, and + a deep workflow can make R1 refuse locally where the server resolves. + - 3.12 and newer, from 1,001 up to the server's limit: the local page refuses and + the server reads, so a deep prompt is malformed locally while the server resolves, + and a deep workflow is ignored locally while the server can refuse it under R1. + Past both limits they agree. `test_local_json_depth_cap_at_its_boundary` checks the + local answer at 999, 1,000 and 1,001 for both kinds and that any server difference + is only one of the two directions above. +- Local roles (PR L3): `\d` in the A1111 settings footer is any Unicode decimal + digit on both sides, but the browser's Unicode version can be newer than the server + Python's, so a footer whose step count uses a digit added after Unicode 15 can differ. + `str.lower()` and `toLowerCase()` differ only for characters no node class name uses. +- A duplicate key in an object enclosing a nest deeper than the running Python's json limit is `malformed` locally and `limited` on that Python. - Decimal exponent limits assume CPython's C `_decimal`; on a `_pydecimal` interpreter the server would read the over-limit exponents the local projection refuses. +- Follow-up (two CPython-JSON emulations, review M6): `local-video.mjs` + (`pythonJsonLoads`/`pythonFloatRepr`, numbers kept as lexemes) and `py-json.mjs` + (`pyJsonLoads`/`pyFloatRepr`, Python value kinds) both emulate `json.loads`; only the + depth cap is shared so far. A fix to one parser can miss the other, so the video + reader should move onto `py-json.mjs` in a later PR. Preserve raw logs, failed traces, paired PNGs, geometry, runtime versions and source hashes before later managed commands clear their output directories. diff --git a/py/api/__init__.py b/py/api/__init__.py index ad5fb7a..d97b359 100644 --- a/py/api/__init__.py +++ b/py/api/__init__.py @@ -108,16 +108,20 @@ STATIC_MIME_TYPES = { ".html": "text/html", } _STATIC_SEPARATORS = re.compile(r"[\\/]+") +# Served by exact request path beside the extension allow-list: the browser's +# copy of the inspection node table (local Inspect resolves with it, #249). +STATIC_EXACT_FILES = {("js", "inspection-semantics.json"): "application/json"} -def _resolve_static_file(root, filepath): +def _resolve_static_file(root, filepath, allowed=STATIC_MIME_TYPES): """Real path of ``filepath`` under ``root``, or None when it must not be served. The request path is untrusted. It is rejected when it is empty, carries a ``..`` segment, is absolute on any platform (a leading slash or backslash, a drive letter such as ``C:`` or a UNC ``\\\\server\\share`` prefix all re-anchor ``os.path.join`` on Windows), has an extension outside - STATIC_MIME_TYPES, or resolves (symlinks included) outside ``root``. + ``allowed`` (STATIC_MIME_TYPES), or resolves (symlinks included) outside + ``root``. """ if not isinstance(filepath, str) or not filepath: return None @@ -130,7 +134,7 @@ def _resolve_static_file(root, filepath): segments = _STATIC_SEPARATORS.split(filepath) if any(segment in ("", ".", "..") for segment in segments): return None - if os.path.splitext(filepath)[1].lower() not in STATIC_MIME_TYPES: + if os.path.splitext(filepath)[1].lower() not in allowed: return None try: root_real = Path(os.path.normcase(os.path.realpath(root))) @@ -499,15 +503,20 @@ class PromptManagerAPI( def _serve_static_file(self, subdir, filepath): """Serve ``web//``; 403 outside it, 404 when missing.""" root = os.path.join(_get_project_root(), "web", subdir) - file_path = _resolve_static_file(root, filepath) + exact = STATIC_EXACT_FILES.get((subdir, filepath)) + # An exact file passes the same containment check, its extension only. + allowed = STATIC_MIME_TYPES if exact is None else {".json"} + file_path = _resolve_static_file(root, filepath, allowed) if file_path is None: return web.Response(text="Forbidden", status=403) + content_type = ( + exact or STATIC_MIME_TYPES[os.path.splitext(file_path)[1].lower()] + ) if not os.path.isfile(file_path): return web.Response(text="Not Found", status=404) - ext = os.path.splitext(file_path)[1].lower() with open(file_path, "rb") as f: content = f.read() - return web.Response(body=content, content_type=STATIC_MIME_TYPES[ext]) + return web.Response(body=content, content_type=content_type) def _serve_html_page(self, filename, title, cache=True): """Serve ``web/``; 404 when missing, 500 when unreadable.""" diff --git a/tests/browser/full-inspector.spec.mjs b/tests/browser/full-inspector.spec.mjs index f1268b1..e4efc5a 100644 --- a/tests/browser/full-inspector.spec.mjs +++ b/tests/browser/full-inspector.spec.mjs @@ -237,9 +237,12 @@ const viewerStructure=details=>details.evaluate(node=>{ test('viewer details hold provenance, raw records and downloads',async({page,request})=>{ await page.setViewportSize({width:1600,height:1100});const reads=await patchInspection(page); await fullFixture(page,request);let details=await viewerDetails(page,'complete.png'); - // The panel content without the cover, then the two disclosures, then the pair send and history buttons (D20). + // The panel content without the cover, D117's Copy settings summary after the facts, then the two disclosures, + // then the pair send and history buttons (D20). expect(await viewerStructure(details)).toEqual({outer:['div','button.send','button'], - inner:['div.panel-heading','p.small','div.tags','section.prompt-section.positive','section.prompt-section.negative','div.tags','dl.meta-grid','details','details']}); + inner:['div.panel-heading','p.small','div.tags','section.prompt-section.positive','section.prompt-section.negative','div.tags','dl.meta-grid','button.settings-summary','details','details']}); + await expect(details.locator(':scope > div > button')).toHaveText('Copy settings summary'); + await expect(details.locator(':scope > div > button.settings-summary')).toHaveCSS('white-space','normal'); await expect(details.locator('.detail-cover,.detail-inner,.detail-footer')).toHaveCount(0); await expect(details.locator('.panel-heading h2')).toHaveText(POSITIVE_TITLE);await expect(details.locator('.panel-heading .chip')).toHaveText('PNG'); await expect(details.locator(':scope > div > p.small')).toHaveText('complete.png'); diff --git a/tests/browser/inspect-concept.spec.mjs b/tests/browser/inspect-concept.spec.mjs index 509cc44..48be585 100644 --- a/tests/browser/inspect-concept.spec.mjs +++ b/tests/browser/inspect-concept.spec.mjs @@ -117,7 +117,7 @@ function measureViewer() { ['dl.meta-grid', node => node.closest('details') ? null : 'facts'], ['details > summary', node => text(node)], ['button.send', node => node.closest('.prompt-section') ? `send ${node.closest('.prompt-section').matches('.positive') ? 'positive' : 'negative'}` : 'send pair'], - ['button', node => /Prompt history/.test(node.textContent) ? 'Prompt history' : null], + ['button', node => /Prompt history/.test(node.textContent) ? 'Prompt history' : text(node) === 'Copy settings summary' ? 'settings summary' : null], ]; const sections = [...rail.querySelectorAll('*')].map(node => { for (const [selector, label] of SECTIONS) if (node.matches(selector)) return label(node); @@ -158,13 +158,18 @@ async function withProductionCopy(page) { }, { COPY, ACCEPT }); } -/** D66: the viewer of a local file is titled by its filename and has no tag chips and no Prompt history. */ +/** + * D66: the viewer of a local file is titled by its filename and has no tag chips and no Prompt history. D117 (LI-4): + * "Copy settings summary" follows the six facts. + */ function mapViewerConcept(reference) { + const sections = reference.sections.filter(section => section !== 'tag chips' && section !== 'Prompt history'); + const facts = sections.indexOf('facts'); return { ...reference, title: FILE, railTitle: FILE, - sections: reference.sections.filter(section => section !== 'tag chips' && section !== 'Prompt history'), + sections: [...sections.slice(0, facts + 1), 'settings summary', ...sections.slice(facts + 1)], }; } @@ -269,9 +274,9 @@ for (const [width, height] of SIZES) for (const theme of THEMES) { // The chooser names the chosen file after a real setInputFiles, as the concept's does. expect(production.initial.chosen).toEqual({ name: '', files: [] }); expect(production.selected.chosen).toEqual({ name: FILE, files: [FILE] }); - // D66 in the rail: no tag chips and no Prompt history; the title is the filename. + // D66 in the rail: no tag chips and no Prompt history; the title is the filename. D117 follows the facts. expect(production.viewer.sections).toEqual(['heading', 'filename', 'badges', 'positive', 'send positive', 'negative', - 'send negative', 'facts', 'File & provenance', 'Workflow & raw metadata', 'send pair']); + 'send negative', 'facts', 'settings summary', 'File & provenance', 'Workflow & raw metadata', 'send pair']); }); } diff --git a/tests/browser/inspector-concept.spec.mjs b/tests/browser/inspector-concept.spec.mjs index 1c8f77e..0a43d7f 100644 --- a/tests/browser/inspector-concept.spec.mjs +++ b/tests/browser/inspector-concept.spec.mjs @@ -45,10 +45,10 @@ function withCategoryScope(inventory) { } /** - * Recorded inspector deviations only (spec §8, TESTING.md D3, D20–D22, D34 and D38); everything else must equal - * production. `reference.viewerPlain` is the concept's own full details - * with its tag chips made plain (D20) and, under a coarse pointer, D34's targets, both at runtime: the browser lays out - * what follows them, as the Images spec's removed toolbar items do. + * Recorded inspector deviations only (spec §8, TESTING.md D3, D20–D22, D34, D38 and D117); everything else must + * equal production. `reference.viewerPlain` is the concept's own full details + * with its tag chips made plain (D20), D117's summary button added and, under a coarse pointer, D34's targets, all at + * runtime: the browser lays out what follows them, as the Images spec's removed toolbar items do. */ export function mapInspectorConcept(reference,{viewport}) { const {panel,viewerPlain,fileControls}=reference; @@ -105,7 +105,11 @@ async function openProductionPanel(page,theme) { await settle(page); } -/** The concept's tag chips in the open viewer as plain `span.chip`s (D20) and D34's coarse targets; returns an undo. */ +/** + * The concept's tag chips in the open viewer as plain `span.chip`s (D20), D34's coarse targets and D117's "Copy + * settings summary" after the six facts (LI-4), drawn as the concept's own plain button (its "Download sample JSON", + * without its action); returns an undo. + */ async function plainViewerChips(page) { const restoreTargets=await mutate(page,{css:D34_COARSE_TARGETS}); await page.evaluate(()=>{ @@ -113,10 +117,15 @@ async function plainViewerChips(page) { const span=document.createElement('span');span.className='chip';span.textContent=button.textContent; button.replaceWith(span);return [span,button]; }); + const summary=document.querySelector('#viewer-details [data-action="download-workflow"]').cloneNode(false); + for(const key of Object.keys(summary.dataset))delete summary.dataset[key]; + summary.textContent='Copy settings summary';summary.classList.add('settings-summary'); + document.querySelector('#viewer-details > div > dl.meta-grid').after(summary);window.__summaryButton=summary; }); await settle(page); return async()=>{ - await page.evaluate(()=>{for(const [span,button] of window.__plainChips)span.replaceWith(button);delete window.__plainChips;}); + await page.evaluate(()=>{for(const [span,button] of window.__plainChips)span.replaceWith(button);delete window.__plainChips; + window.__summaryButton.remove();delete window.__summaryButton;}); await restoreTargets(); }; } @@ -342,7 +351,7 @@ for(const [width,height] of SIZES)test(`image tags saved on the concept image ke // The comparison is only worth something if it notices a change (spec §7 mutation check): on the panel one CSS // mutation (the role label's letter spacing) and one DOM mutation (the footer removed); in the viewer (final review m5) -// its pair actions removed and D38's Show in folder removed; each applied after an exact match. +// its pair actions removed, D38's Show in folder removed and D117's summary removed; each applied after an exact match. test('inspector comparison detects mutations',async({page})=>{ test.setTimeout(120_000); const viewport={width:1600,height:1100}; @@ -366,6 +375,9 @@ test('inspector comparison detects mutations',async({page})=>{ expect(()=>assertInspectorMatch(reference,withoutActions,viewport)).toThrow(/viewerDetails\.actions/); const withoutReveal=await viewerMutated({remove:['#viewer-details button[aria-label$=" in folder"]']}); expect(()=>assertInspectorMatch(reference,withoutReveal,viewport)).toThrow(/fileControls/); + // D117: the summary action after the facts is part of the mapped concept, so losing it is a difference. + const withoutSummary=await viewerMutated({remove:['#viewer-details > div > button']}); + expect(()=>assertInspectorMatch(reference,withoutSummary,viewport)).toThrow(/viewerDetails\.structure\.inner/); assertInspectorMatch(reference,await viewerMutated(),viewport); await mutate(page,{remove:['#image-inspector > .detail-footer']}); diff --git a/tests/browser/workspace-history.spec.mjs b/tests/browser/workspace-history.spec.mjs index e08a1a9..48f8107 100644 --- a/tests/browser/workspace-history.spec.mjs +++ b/tests/browser/workspace-history.spec.mjs @@ -494,6 +494,23 @@ test('the inline current file names its prompts apart from the frozen run fields expect(await exact(dialog(page).getByRole('region',{name:'Positive prompt',exact:true}).locator('p.prompt-text'))).toBe(before); }); +// LI-4 (D117): the recorded history's current-file viewer is the shared full inspector, so it copies the legacy summary. +test('the current file viewer copies its settings summary',async({page})=>{ + await page.addInitScript(()=>{window.__copied=[];Object.defineProperty(navigator,'clipboard',{configurable:true,value:{writeText:async text=>{window.__copied.push(text);}}});}); + await page.route(url=>url.pathname.endsWith('/inspection'),async route=>{const response=await route.fetch();const body=await response.json(); + body.prompts={positive:{status:'resolved',text:'current file positive',source:'graph-inferred'},negative:{status:'resolved',text:'current file negative',source:'graph-inferred'}}; + await route.fulfill({response,json:body});}); + await open(page,page.fixture.detail_id);await marker(page,page.fixture.runs.shared).click();await expect(dialog(page).locator('[data-receipt]')).toHaveCount(5); + await dialog(page).locator('[data-receipt]').first().getByRole('button',{name:'View current file',exact:true}).click(); + const details=page.locator('dialog#viewer-dialog #viewer-details');await expect(details.locator('.panel-heading')).toBeVisible(); + const facts=await details.locator(':scope > div > dl.meta-grid dd').allTextContents(); + await details.getByRole('button',{name:'Copy settings summary',exact:true}).click(); + await expect(page.locator('#workspace-toast')).toHaveText('Settings summary copied.'); + const [seed,steps,cfg,sampler,,model]=facts; + expect(await page.evaluate(()=>window.__copied)).toEqual([[`Checkpoint: ${model}`,'Positive Prompt: current file positive','Negative Prompt: current file negative', + `Steps: ${steps}`,`CFG Scale: ${cfg}`,`Sampler: ${sampler}`,`Seed: ${seed}`].join('\n').replace(/: (Not recorded|Unresolved|Ambiguous|Unavailable within inspection limits)(?=\n|$)/g,': Unknown')]); +}); + test('the recorded run dialog with a resolved current file has no duplicate button or region names',async({page})=>{ await page.route(url=>url.pathname.endsWith('/inspection'),async route=>{const response=await route.fetch();const body=await response.json(); body.prompts={positive:{status:'resolved',text:'current file positive',source:'graph-inferred'},negative:{status:'resolved',text:'current file negative',source:'graph-inferred'}}; diff --git a/tests/browser/workspace-inspect.spec.mjs b/tests/browser/workspace-inspect.spec.mjs index 1502207..5d19793 100644 --- a/tests/browser/workspace-inspect.spec.mjs +++ b/tests/browser/workspace-inspect.spec.mjs @@ -207,6 +207,40 @@ test('chooser opens the shared full inspector without a second read', async ({ p expect(await page.evaluate(() => window.__slices)).toBe(0); }); +// PR L3 Task 10: local roles are the server inspector's (local-resolver.mjs), so for every parity PNG the rail shows the +// prompts, their status lines and the facts Images shows for the same bytes in the output folder. +const PARITY_PNGS = ['f01b', 'f02', 'f03', 'f06a', 'f06b', 'f06c', 'f06d', 'f06e', 'f07a', 'f07b', 'f08', 'f09', 'f10', 'f11', 'f12', + 'f14', 'f15', 'f16', 'f17', 'f19', 'f20', 'f21', 'f22', 'f23', 'f24']; +const roleSections = locator => locator.evaluate(node => [...node.querySelectorAll('.prompt-section')].map(item => item.textContent)); + +test('chooser shows the Images roles and resolution for every parity PNG', async ({ page, request }) => { + test.slow(); + for (const name of PARITY_PNGS) { + await expect(await request.post('/__test__/add-local-inspect-file', { data: { name: `${name}.png` } })).toBeOK(); + } + const served = {}; + await page.goto(`${workspace}#/images`); + for (const name of PARITY_PNGS) { + await page.locator(`article[data-image-key="0:local-inspect/${name}.png"] .image-open`).click(); + await expect(viewer(page).locator('#viewer-title')).toHaveText(`${name}.png`); + await expect(rail(page).locator('.panel-heading')).toBeVisible(); + await expect(rail(page).locator('.prompt-section')).not.toHaveCount(0); + served[name] = { content: await railContent(rail(page)), roles: await roleSections(rail(page)) }; + await page.keyboard.press('Escape'); + await expect(viewer(page)).toHaveCount(0); + } + await openInspect(page); + for (const name of PARITY_PNGS) { + await choose(page, parityPng(`${name}.png`)); + await openViewer(page); + await expect(viewer(page).locator('#viewer-title')).toHaveText(`${name}.png`); + await expect(rail(page).locator('.prompt-section')).not.toHaveCount(0); + expect({ content: await railContent(rail(page)), roles: await roleSections(rail(page)) }, name).toEqual(served[name]); + await page.keyboard.press('Escape'); + await expect(viewer(page)).toHaveCount(0); + } +}); + test('Import → Inspect a local image lands here', async ({ page }) => { await page.goto(`${workspace}#/images`); await page.getByRole('button', { name: 'Import', exact: true }).click(); @@ -656,13 +690,19 @@ test('local roles send exactly', async ({ page, context }) => { test('local inspection makes no content request or storage write', async ({ page }) => { await instrument(page); - await openInspect(page); - // The shell's own reads (counts, Activity) settle before the baseline. - await expect(page.locator('aside.sidebar nav [data-route="images"] .nav-count')).toBeAttached(); - const baseline = (await urls(page)).writes.length; const requests = []; page.on('request', request => requests.push({ url: request.url(), method: request.method(), body: request.postData() })); page.on('websocket', socket => requests.push({ url: socket.url(), method: 'WS', body: null })); + const table = /\/prompt_manager\/js\/inspection-semantics\.json$/; + const tableRead = page.waitForResponse(response => table.test(response.url())); + await openInspect(page); + // The one static file Inspect reads, its node table, is fetched as the page mounts: before any selection. + expect((await tableRead).ok()).toBe(true); + // The shell's own reads (counts, Activity) settle before the baseline. + await expect(page.locator('aside.sidebar nav [data-route="images"] .nav-count')).toBeAttached(); + const baseline = (await urls(page)).writes.length; + const before = requests.length; + expect(requests.filter(entry => table.test(entry.url))).toHaveLength(1); for (const file of [sendablePng('private-name.png'), localFixture('core-tags.webm', 'video/webm', 'private-clip.webm')]) { await choose(page, file); await openViewer(page); @@ -670,7 +710,8 @@ test('local inspection makes no content request or storage write', async ({ page await page.keyboard.press('Escape'); await expect(viewer(page)).toHaveCount(0); } - const network = requests.filter(entry => !entry.url.startsWith('blob:') && !entry.url.startsWith('data:')); + const network = requests.slice(before).filter(entry => !entry.url.startsWith('blob:') && !entry.url.startsWith('data:')); + expect(requests.filter(entry => table.test(entry.url)), 'the table is read once per page').toHaveLength(1); expect(network.filter(entry => /private|lighthouse|fox/.test(`${entry.url} ${entry.body ?? ''}`))).toEqual([]); expect(network.filter(entry => entry.method !== 'GET')).toEqual([]); expect(network.filter(entry => !/\/prompt_manager\/(activity|images\/output|library|vocabulary)/.test(entry.url))).toEqual([]); @@ -689,3 +730,80 @@ test('touch layout at 390 has no horizontal overflow at 200% zoom', async ({ pag expect(area).toBe(true); } }); + +// LI-4 (D117): "Copy settings summary" after the six facts is the legacy metadata page's COPY ALL, in the shared full +// inspector, so a file served in Images and the same bytes chosen here copy the same summary of what the rail shows. +/** Records clipboard writes in the page, or (`clipboard: false`) leaves the page without a clipboard. */ +async function stubClipboard(page, { clipboard = true } = {}) { + await page.addInitScript(available => { + window.__copied = []; + Object.defineProperty(navigator, 'clipboard', { configurable: true, + value: available ? { writeText: async text => { window.__copied.push(text); } } : undefined }); + }, clipboard); +} +/** The summary the rail's own prompts and facts make, in the legacy COPY ALL lines and placeholders. */ +const expectedSummary = locator => locator.evaluate(node => { + const facts = Object.fromEntries([...node.querySelectorAll(':scope .meta-grid:not(details .meta-grid) > div')] + .map(item => [item.querySelector('dt').textContent, item.querySelector('dd').textContent])); + // A confirmed prompt has its Copy action; an explicitly empty one takes the legacy placeholder too. + const prompt = role => { + const text = node.querySelector(`.prompt-section.${role} [data-copy-role]`) ? node.querySelector(`.prompt-section.${role} p.prompt-text`).textContent : null; + return text === `No ${role} prompt (explicitly empty)` ? null : text; + }; + return [`Checkpoint: ${facts.Model}`, `Positive Prompt: ${prompt('positive') ?? 'No prompt found'}`, + `Negative Prompt: ${prompt('negative') ?? 'No negative prompt found'}`, `Steps: ${facts.Steps}`, `CFG Scale: ${facts.CFG}`, + `Sampler: ${facts.Sampler}`, `Seed: ${facts.Seed}`].join('\n'); +}); +async function copySummary(page) { + const button = rail(page).getByRole('button', { name: 'Copy settings summary', exact: true }); + // It follows the six facts, before "File & provenance". + expect(await button.evaluate(node => [node.previousElementSibling?.localName, node.nextElementSibling?.localName])).toEqual(['dl', 'details']); + await button.click(); +} + +test('Copy settings summary copies the same legacy summary in Images and Inspect', async ({ page, request }) => { + await stubClipboard(page); + await expect(await request.post('/__test__/add-local-inspect-file', { data: { name: 'f02.png' } })).toBeOK(); + await page.goto(`${workspace}#/images`); + await page.locator('article[data-image-key="0:local-inspect/f02.png"] .image-open').click(); + await expect(rail(page).locator('.prompt-section.positive p.prompt-text')).toBeVisible(); + const served = await expectedSummary(rail(page)); + expect(served).toMatch(/^Checkpoint: .+\nPositive Prompt: [\s\S]+\nNegative Prompt: [\s\S]+\nSteps: .+\nCFG Scale: .+\nSampler: .+\nSeed: .+$/); + expect(served).not.toContain('Unknown'); + await copySummary(page); + await expect(page.locator('#workspace-toast')).toHaveText('Settings summary copied.'); + expect(await page.evaluate(() => window.__copied)).toEqual([served]); + await page.keyboard.press('Escape'); + await expect(viewer(page)).toHaveCount(0); + + await openInspect(page); + await choose(page, parityPng('f02.png')); + await openViewer(page); + expect(await expectedSummary(rail(page))).toBe(served); + await copySummary(page); + await expect.poll(() => page.evaluate(() => window.__copied)).toEqual([served, served]); + // The panel variant (the Images side panel) keeps the concept's footer: no summary action there. + await page.keyboard.press('Escape'); + await page.goto(`${workspace}#/images`); + await expect(page.locator('#image-inspector .panel-heading')).toBeVisible(); + await expect(page.locator('#image-inspector').getByRole('button', { name: 'Copy settings summary', exact: true })).toHaveCount(0); +}); + +test('Copy settings summary without a clipboard opens the select-to-copy dialog', async ({ page }) => { + await stubClipboard(page, { clipboard: false }); + await openInspect(page); + await choose(page, sendablePng()); + await openViewer(page); + const summary = await expectedSummary(rail(page)); + expect(summary).toContain(`Positive Prompt: ${POSITIVE_LINES}`); + await copySummary(page); + const fallback = page.getByRole('dialog', { name: 'Copy settings summary', exact: true }); + await expect(fallback).toBeVisible(); + await expect(fallback.getByRole('textbox', { name: 'Select and copy this text', exact: true })).toHaveValue(summary); + await expect(fallback.getByRole('textbox', { name: 'Select and copy this text', exact: true })).toBeFocused(); + await page.keyboard.press('Escape'); + await expect(fallback).toHaveCount(0); + // Escape closes only the copy dialog; focus returns to the action in the still-open viewer. + await expect(viewer(page)).toBeVisible(); + await expect(rail(page).getByRole('button', { name: 'Copy settings summary', exact: true })).toBeFocused(); +}); diff --git a/tests/fixtures/local-inspect/resolver-vectors.json b/tests/fixtures/local-inspect/resolver-vectors.json new file mode 100644 index 0000000..55e7a71 --- /dev/null +++ b/tests/fixtures/local-inspect/resolver-vectors.json @@ -0,0 +1 @@ +{"vectors": [{"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "encode", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "empty-positive", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" …\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": ""}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "feff-positive", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "no-negative", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": null, \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Negative input is absent", "reason_code": null, "sampler_id": "3", "state": "absent"}}, "name": "negative-missing-input", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "float-slot", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0.0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "bool-slot", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", true], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "int-id", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [6, 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "dangling", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"60\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (CLIPTextEncode).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (CLIPTextEncode).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "CLIPTextEncode", "id": "6"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "wrong-slot", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 3], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Cyclic prompt graph", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "cycle", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"8\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Reroute input is not uniquely identifiable", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "reroute-ambiguous", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"6\", 0], \"in\": [\"6\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "last wins"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "duplicate-key", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"last wins\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "nan-input", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": NaN, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": null, "id": "6"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "class-type-number", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": 1.5, \"inputs\": {\"text\": \"x\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": null, "id": "6"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "class-type-missing", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"inputs\": {\"text\": \"x\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "inputs-list", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": [\"x\"]}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "API graph is missing or malformed", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "prompt-list", "records": {"prompt": "[1, 2]"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "API graph is missing or malformed", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "prompt-empty", "records": {"prompt": "{}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Prompt evidence is malformed", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "prompt-bom", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Prompt evidence is malformed", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "huge-int", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Prompt evidence is malformed", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "only-execution", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "No supported sampler was found.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "No supported sampler was found.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "No supported sampler pair found (saw XSampler, YGuider)", "reason_code": "no-sampler", "sampler_id": null, "state": "unresolved"}}, "name": "no-sampler", "records": {"prompt": "{\"1\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"x\", \"clip\": [\"4\", 1]}}, \"2\": {\"class_type\": \"XSampler\", \"inputs\": {\"positive\": [\"1\", 0]}}, \"9\": {\"class_type\": \"YGuider\", \"inputs\": {\"guider\": [\"1\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "No supported sampler was found.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "No supported sampler was found.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "No supported sampler pair found", "reason_code": "no-sampler", "sampler_id": null, "state": "unresolved"}}, "name": "no-sampler-plain", "records": {"prompt": "{\"1\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"x\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "sdxl-equal", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"a\", \"text_l\": \"a\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "sdxl-one", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"a\", \"text_l\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "CLIPTextEncodeSDXL", "id": "8"}, "reason": "Encoder parts have different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "sdxl-differ", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"a\", \"text_l\": \"b\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "t"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "smz-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"smZ CLIPTextEncode\", \"inputs\": {\"text\": \"t\", \"text_g\": \"g\", \"text_l\": \"g\", \"with_SDXL\": false}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (smZ CLIPTextEncode).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (smZ CLIPTextEncode).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "smZ CLIPTextEncode", "id": "8"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "smz-true", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"smZ CLIPTextEncode\", \"inputs\": {\"text\": \"t\", \"text_g\": \"g\", \"text_l\": \"g\", \"with_SDXL\": true}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed string node setting", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "smz-1", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"smZ CLIPTextEncode\", \"inputs\": {\"text\": \"t\", \"text_g\": \"g\", \"text_l\": \"g\", \"with_SDXL\": 1}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (smZ CLIPTextEncode).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (smZ CLIPTextEncode).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "smZ CLIPTextEncode", "id": "8"}, "reason": "Linked string node setting", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "smz-[\"9\", 0]", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"smZ CLIPTextEncode\", \"inputs\": {\"text\": \"t\", \"text_g\": \"g\", \"text_l\": \"g\", \"with_SDXL\": [\"9\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "zeroed-conditioning", "status": "resolved", "text": ""}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "zeroed", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"8\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"6\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "passthrough", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"6\", 0], \"guidance\": 3.5}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "controlnet-slot1", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"ControlNetApplyAdvanced\", \"inputs\": {\"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "combine-equal", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"9\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"6\", 0], \"conditioning_2\": [\"9\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "ConditioningCombine", "id": "8"}, "reason": "Combined conditioning has different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "combine-differ", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"6\", 0], \"conditioning_2\": [\"7\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "neg"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "select-true", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"10\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"6\", 0], \"on_false\": [\"7\", 0]}}, \"10\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"neg\", \"clip\": [\"4\", 1]}}, \"9\": {\"class_type\": \"PrimitiveBoolean\", \"inputs\": {\"value\": true}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "neg"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "select-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"10\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"6\", 0], \"on_false\": [\"7\", 0]}}, \"10\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"neg\", \"clip\": [\"4\", 1]}}, \"9\": {\"class_type\": \"PrimitiveBoolean\", \"inputs\": {\"value\": true}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Selector branches have different prompts", "reason_code": null, "sampler_id": "3", "state": "ambiguous"}}, "name": "select-[\"9\", 0]", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"10\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"9\", 0], \"on_true\": [\"6\", 0], \"on_false\": [\"7\", 0]}}, \"10\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"neg\", \"clip\": [\"4\", 1]}}, \"9\": {\"class_type\": \"PrimitiveBoolean\", \"inputs\": {\"value\": true}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed selector condition", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "select-1", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"10\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": 1, \"on_true\": [\"6\", 0], \"on_false\": [\"7\", 0]}}, \"10\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"neg\", \"clip\": [\"4\", 1]}}, \"9\": {\"class_type\": \"PrimitiveBoolean\", \"inputs\": {\"value\": true}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed selector condition", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "select-\"true\"", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"10\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": \"true\", \"on_true\": [\"6\", 0], \"on_false\": [\"7\", 0]}}, \"10\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"neg\", \"clip\": [\"4\", 1]}}, \"9\": {\"class_type\": \"PrimitiveBoolean\", \"inputs\": {\"value\": true}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "select-converge", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"9\", 0], \"on_true\": [\"6\", 0], \"on_false\": [\"11\", 0]}}, \"11\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Selector branches have different prompts", "reason_code": null, "sampler_id": "3", "state": "ambiguous"}}, "name": "select-shared", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"12\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"9\", 0], \"on_true\": [\"6\", 0], \"on_false\": [\"7\", 0]}}, \"12\": {\"class_type\": \"Switch conditioning [Crystools]\", \"inputs\": {\"boolean\": [\"9\", 0], \"on_true\": [\"7\", 0], \"on_false\": [\"6\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "8"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "runtime", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptSearchList\", \"inputs\": {}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoderxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoderxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoderxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "id": "8"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "unknown-encoder", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"FancyEncoderxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\", \"inputs\": {\"text\": \"x\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": " multi\nline "}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "primitive", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \" multi\\nline \"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Output slot has an incompatible type", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "string-kind-mismatch", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"x\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": " a , "}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "string-concatenate", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \" a \", \"string_b\": \"\", \"delimiter\": \", \"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a b"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "text-concatenate-\"true\"", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \" b \", \"text_a\": \" a\", \"text_aa\": \"x\", \"text_c\": \"\", \"clean_whitespace\": \"true\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": " a b "}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "text-concatenate-\"False\"", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \" b \", \"text_a\": \" a\", \"text_aa\": \"x\", \"text_c\": \"\", \"clean_whitespace\": \"False\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a b"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "text-concatenate-true", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \" b \", \"text_a\": \" a\", \"text_aa\": \"x\", \"text_c\": \"\", \"clean_whitespace\": true}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a b"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "text-concatenate-\"TRUE\"", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \" b \", \"text_a\": \" a\", \"text_aa\": \"x\", \"text_c\": \"\", \"clean_whitespace\": \"TRUE\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": " a b "}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "text-concatenate-0", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \" b \", \"text_a\": \" a\", \"text_aa\": \"x\", \"text_c\": \"\", \"clean_whitespace\": 0}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "ab"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "strip-newlines-true", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\n a\\nb \\n\", \"strip_newlines\": true}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "\n a\nb \n"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "strip-newlines-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\n a\\nb \\n\", \"strip_newlines\": false}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed string node setting", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "strip-newlines-1", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\n a\\nb \\n\", \"strip_newlines\": 1}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": " | b"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "join-multi-3-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\", \"string_2\": \"b\", \"string_3\": \"\", \"string_4\": \"d\", \"inputcount\": 3, \"delimiter\": \" | \", \"return_list\": false}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "join-multi-1-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\", \"string_2\": \"b\", \"string_3\": \"\", \"string_4\": \"d\", \"inputcount\": 1, \"delimiter\": \" | \", \"return_list\": false}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed string node setting", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "join-multi-0-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\", \"string_2\": \"b\", \"string_3\": \"\", \"string_4\": \"d\", \"inputcount\": 0, \"delimiter\": \" | \", \"return_list\": false}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed string node setting", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "join-multi-1001-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\", \"string_2\": \"b\", \"string_3\": \"\", \"string_4\": \"d\", \"inputcount\": 1001, \"delimiter\": \" | \", \"return_list\": false}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (JoinStringMulti).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (JoinStringMulti).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "JoinStringMulti", "id": "8"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "join-multi-2-true", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\", \"string_2\": \"b\", \"string_3\": \"\", \"string_4\": \"d\", \"inputcount\": 2, \"delimiter\": \" | \", \"return_list\": true}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed string node setting", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "join-multi-2.0-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\", \"string_2\": \"b\", \"string_3\": \"\", \"string_4\": \"d\", \"inputcount\": 2.0, \"delimiter\": \" | \", \"return_list\": false}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed string node setting", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "join-multi-true-false", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"8\", 0], \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\", \"string_2\": \"b\", \"string_3\": \"\", \"string_4\": \"d\", \"inputcount\": true, \"delimiter\": \" | \", \"return_list\": false}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "before main"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "prompt-manager", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"main\", \"prepend_text\": \" before \", \"append_text\": \"\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "prompt-manager-null-prepend", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"main\", \"prepend_text\": null, \"append_text\": \"\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "lead,main"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "historical-PromptManagerV2-0", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \" main \", \"negative_text\": \" neg \", \"prepend_text\": \"lead,\", \"append_text\": null}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "neg"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "historical-PromptManagerV2-1", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 1], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \" main \", \"negative_text\": \" neg \", \"prepend_text\": \"lead,\", \"append_text\": null}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "lead,main"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "historical-PromptManagerPositive-0", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \" main \", \"negative_text\": \" neg \", \"prepend_text\": \"lead,\", \"append_text\": null}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "main"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "historical-PromptManagerNegative-0", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerNegative\", \"inputs\": {\"text\": \" main \", \"negative_text\": \" neg \", \"prepend_text\": \"lead,\", \"append_text\": null}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blur"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "pair-graph", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "execution", "status": "resolved", "text": "blur"}, "positive": {"source": "execution", "status": "resolved", "text": "fox executed"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "pair-execution", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blur"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "pair-execution-other-node", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"99\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Execution evidence does not match recorded node inputs", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "pair-execution-mismatch", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"8\": {\"records\": [{\"text\": \"other\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Negative execution text must be unchanged", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "pair-execution-negative-changed", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"x\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "execution", "status": "resolved", "text": "blur"}, "positive": {"source": "execution", "status": "resolved", "text": "fox executed"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "pair-execution-version-true", "records": {"comfyassets_prompt_pairs": "{\"version\": true, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "execution", "status": "resolved", "text": "blur"}, "positive": {"source": "execution", "status": "resolved", "text": "fox executed"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "pair-execution-version-float", "records": {"comfyassets_prompt_pairs": "{\"version\": 1.0, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "execution", "status": "resolved", "text": "blur"}, "positive": {"source": "execution", "status": "resolved", "text": "fox executed"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "pair-execution-truncated", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"truncated\": [], \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Malformed execution evidence JSON", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "pair-execution-bad-json", "records": {"comfyassets_prompt_pairs": "{nope", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Multiple distinct executions have no image anchor", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "pair-execution-two-records", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}, {\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"other\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"fox\", \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "execution", "status": "resolved", "text": "blur"}, "positive": {"source": "execution", "status": "resolved", "text": "fox executed"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "pair-execution-runtime-input", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": [\"9\", 0], \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}, \"9\": {\"class_type\": \"PromptSearchList\", \"inputs\": {}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (PromptManagerText).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (PromptManagerText).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "PromptManagerText", "id": "9"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "pair-execution-runtime-wrong-slot", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"8\": {\"records\": [{\"text\": \"fox\", \"negative_text\": \"blur\", \"positive_text\": \"fox executed\", \"negative_effective_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"8\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": [\"9\", 2], \"negative_text\": \"blur\", \"prepend_text\": \"\", \"append_text\": \"\"}}, \"9\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"x\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "custom-cfg", "records": {"prompt": "{\"3\": {\"class_type\": \"SamplerCustomAdvanced\", \"inputs\": {\"noise\": [\"20\", 0], \"guider\": [\"21\", 0], \"sampler\": [\"22\", 0], \"sigmas\": [\"23\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"21\": {\"class_type\": \"CFGGuider\", \"inputs\": {\"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"model\": [\"4\", 0], \"cfg\": 5}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Guider has no negative input", "reason_code": null, "sampler_id": "3", "state": "absent"}}, "name": "custom-basic", "records": {"prompt": "{\"3\": {\"class_type\": \"SamplerCustomAdvanced\", \"inputs\": {\"noise\": [\"20\", 0], \"guider\": [\"21\", 0], \"sampler\": [\"22\", 0], \"sigmas\": [\"23\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"21\": {\"class_type\": \"BasicGuider\", \"inputs\": {\"conditioning\": [\"6\", 0], \"model\": [\"4\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Guider has no negative input", "reason_code": null, "sampler_id": "3", "state": "absent"}}, "name": "custom-reroute-guider", "records": {"prompt": "{\"3\": {\"class_type\": \"SamplerCustomAdvanced\", \"inputs\": {\"noise\": [\"20\", 0], \"guider\": [\"21\", 0], \"sampler\": [\"22\", 0], \"sigmas\": [\"23\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"21\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"24\", 0]}}, \"24\": {\"class_type\": \"BasicGuider\", \"inputs\": {\"conditioning\": [\"6\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (DualCFGGuider).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (DualCFGGuider).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "DualCFGGuider", "id": "21"}, "reason": "Unsupported guider", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "custom-unknown-guider", "records": {"prompt": "{\"3\": {\"class_type\": \"SamplerCustomAdvanced\", \"inputs\": {\"noise\": [\"20\", 0], \"guider\": [\"21\", 0], \"sampler\": [\"22\", 0], \"sigmas\": [\"23\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"21\": {\"class_type\": \"DualCFGGuider\", \"inputs\": {\"cond1\": [\"6\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (KSamplerPreview).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (KSamplerPreview).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "KSamplerPreview", "id": "30"}, "reason": "Unsupported latent ancestry", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "latent-stage", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"LatentUpscale\", \"inputs\": {\"samples\": [\"30\", 0]}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"30\": {\"class_type\": \"KSamplerPreview\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"6\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "latent-encode", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"VAEEncode\", \"inputs\": {\"pixels\": [\"31\", 0], \"vae\": [\"4\", 2]}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"31\": {\"class_type\": \"LoadImage\", \"inputs\": {\"image\": \"x.png\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Cyclic latent ancestry", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "latent-cycle", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"LatentUpscale\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "override-ignored-\"\"", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0], \"wildcard\": \"\"}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "override-ignored-\"wild\"", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0], \"wildcard\": \"wild\"}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "override-ignored-[\"6\", 0]", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0], \"wildcard\": [\"6\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt exceeds inspection limits.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt exceeds inspection limits.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Resolution depth limit reached", "reason_code": "depth-limit", "sampler_id": "3", "state": "unresolved"}}, "name": "depth-limit", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"r69\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"deep\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"r0\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"6\", 0]}}, \"r1\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r0\", 0]}}, \"r2\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r1\", 0]}}, \"r3\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r2\", 0]}}, \"r4\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r3\", 0]}}, \"r5\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r4\", 0]}}, \"r6\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r5\", 0]}}, \"r7\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r6\", 0]}}, \"r8\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r7\", 0]}}, \"r9\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r8\", 0]}}, \"r10\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r9\", 0]}}, \"r11\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r10\", 0]}}, \"r12\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r11\", 0]}}, \"r13\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r12\", 0]}}, \"r14\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r13\", 0]}}, \"r15\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r14\", 0]}}, \"r16\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r15\", 0]}}, \"r17\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r16\", 0]}}, \"r18\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r17\", 0]}}, \"r19\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r18\", 0]}}, \"r20\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r19\", 0]}}, \"r21\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r20\", 0]}}, \"r22\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r21\", 0]}}, \"r23\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r22\", 0]}}, \"r24\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r23\", 0]}}, \"r25\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r24\", 0]}}, \"r26\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r25\", 0]}}, \"r27\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r26\", 0]}}, \"r28\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r27\", 0]}}, \"r29\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r28\", 0]}}, \"r30\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r29\", 0]}}, \"r31\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r30\", 0]}}, \"r32\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r31\", 0]}}, \"r33\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r32\", 0]}}, \"r34\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r33\", 0]}}, \"r35\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r34\", 0]}}, \"r36\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r35\", 0]}}, \"r37\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r36\", 0]}}, \"r38\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r37\", 0]}}, \"r39\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r38\", 0]}}, \"r40\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r39\", 0]}}, \"r41\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r40\", 0]}}, \"r42\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r41\", 0]}}, \"r43\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r42\", 0]}}, \"r44\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r43\", 0]}}, \"r45\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r44\", 0]}}, \"r46\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r45\", 0]}}, \"r47\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r46\", 0]}}, \"r48\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r47\", 0]}}, \"r49\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r48\", 0]}}, \"r50\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r49\", 0]}}, \"r51\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r50\", 0]}}, \"r52\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r51\", 0]}}, \"r53\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r52\", 0]}}, \"r54\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r53\", 0]}}, \"r55\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r54\", 0]}}, \"r56\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r55\", 0]}}, \"r57\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r56\", 0]}}, \"r58\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r57\", 0]}}, \"r59\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r58\", 0]}}, \"r60\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r59\", 0]}}, \"r61\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r60\", 0]}}, \"r62\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r61\", 0]}}, \"r63\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r62\", 0]}}, \"r64\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r63\", 0]}}, \"r65\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r64\", 0]}}, \"r66\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r65\", 0]}}, \"r67\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r66\", 0]}}, \"r68\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r67\", 0]}}, \"r69\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r68\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "deep"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "depth-near", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"r60\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"deep\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"r0\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"6\", 0]}}, \"r1\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r0\", 0]}}, \"r2\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r1\", 0]}}, \"r3\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r2\", 0]}}, \"r4\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r3\", 0]}}, \"r5\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r4\", 0]}}, \"r6\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r5\", 0]}}, \"r7\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r6\", 0]}}, \"r8\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r7\", 0]}}, \"r9\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r8\", 0]}}, \"r10\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r9\", 0]}}, \"r11\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r10\", 0]}}, \"r12\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r11\", 0]}}, \"r13\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r12\", 0]}}, \"r14\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r13\", 0]}}, \"r15\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r14\", 0]}}, \"r16\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r15\", 0]}}, \"r17\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r16\", 0]}}, \"r18\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r17\", 0]}}, \"r19\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r18\", 0]}}, \"r20\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r19\", 0]}}, \"r21\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r20\", 0]}}, \"r22\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r21\", 0]}}, \"r23\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r22\", 0]}}, \"r24\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r23\", 0]}}, \"r25\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r24\", 0]}}, \"r26\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r25\", 0]}}, \"r27\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r26\", 0]}}, \"r28\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r27\", 0]}}, \"r29\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r28\", 0]}}, \"r30\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r29\", 0]}}, \"r31\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r30\", 0]}}, \"r32\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r31\", 0]}}, \"r33\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r32\", 0]}}, \"r34\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r33\", 0]}}, \"r35\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r34\", 0]}}, \"r36\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r35\", 0]}}, \"r37\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r36\", 0]}}, \"r38\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r37\", 0]}}, \"r39\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r38\", 0]}}, \"r40\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r39\", 0]}}, \"r41\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r40\", 0]}}, \"r42\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r41\", 0]}}, \"r43\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r42\", 0]}}, \"r44\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r43\", 0]}}, \"r45\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r44\", 0]}}, \"r46\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r45\", 0]}}, \"r47\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r46\", 0]}}, \"r48\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r47\", 0]}}, \"r49\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r48\", 0]}}, \"r50\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r49\", 0]}}, \"r51\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r50\", 0]}}, \"r52\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r51\", 0]}}, \"r53\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r52\", 0]}}, \"r54\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r53\", 0]}}, \"r55\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r54\", 0]}}, \"r56\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r55\", 0]}}, \"r57\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r56\", 0]}}, \"r58\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r57\", 0]}}, \"r59\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r58\", 0]}}, \"r60\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"r59\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Saved PromptManager text was overwritten by another node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "overwritten", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1], \"search_text\": \"\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1]}}}", "workflow": "{\"nodes\": [{\"id\": 6, \"type\": \"PromptManager\", \"widgets_values\": [\"own text\"]}, {\"id\": 7, \"type\": \"PromptManager\", \"widgets_values\": [\"other text\"]}]}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Saved PromptManager text was overwritten by another node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "overwritten-subgraph", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"1:6\", 0], \"negative\": [\"1:7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"1:6\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"same\", \"clip\": [\"4\", 1]}}, \"1:7\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"same\"}}}", "workflow": "{\"nodes\": [{\"id\": 1, \"type\": \"sub-a\", \"widgets_values\": []}], \"definitions\": {\"subgraphs\": [{\"id\": \"sub-a\", \"nodes\": [{\"id\": 6, \"type\": \"PromptManagerFocused\", \"widgets_values\": {\"text\": \"a\"}}, {\"id\": 7, \"type\": \"PromptManagerFocused\", \"widgets_values\": [\"b\"]}]}]}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "shared"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "shared"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "overwritten-bad-workflow", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1], \"search_text\": \"\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1]}}}", "workflow": "{bad"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "shared"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "shared"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "workflow-type-list", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1], \"search_text\": \"\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1]}}}", "workflow": "{\"nodes\": [{\"id\": 6, \"type\": \"PromptManager\"}, {\"id\": 8, \"type\": [\"PromptManager\"]}]}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "shared"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "shared"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "workflow-type-dict", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1], \"search_text\": \"\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1]}}}", "workflow": "{\"nodes\": [{\"id\": 6, \"type\": \"PromptManager\"}, {\"id\": 8, \"type\": {\"a\": 1}}]}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "same"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "same"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "workflow-type-in-subgraph", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"1:6\", 0], \"negative\": [\"1:7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"1:6\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"same\", \"clip\": [\"4\", 1]}}, \"1:7\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"same\"}}}", "workflow": "{\"nodes\": [{\"id\": 1, \"type\": \"sub-a\", \"widgets_values\": []}], \"definitions\": {\"subgraphs\": [{\"id\": \"sub-a\", \"nodes\": [{\"id\": 2, \"type\": [1]}]}]}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Saved PromptManager text was overwritten by another node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "workflow-type-skipped-keeps-overwritten", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1], \"search_text\": \"\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1]}}}", "workflow": "{\"nodes\": [{\"id\": 6, \"type\": \"PromptManager\", \"widgets_values\": [\"own text\"]}, {\"id\": 8, \"type\": [\"PromptManager\"]}, {\"id\": 7, \"type\": \"PromptManager\", \"widgets_values\": [\"other text\"]}]}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "shared"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "shared"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "workflow-type-without-id", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1], \"search_text\": \"\"}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"shared\", \"clip\": [\"4\", 1]}}}", "workflow": "{\"nodes\": [{\"id\": true, \"type\": [\"x\"]}, \"skipped\"]}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Every sampler branch uses the same prompt pair", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "several-samplers", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "detailer", "records": {"prompt": "{\"3\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"5\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"wildcard\": \"\"}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "embedded-parameters", "status": "resolved", "text": "blur"}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "parameters-only", "records": {"parameters": "a fox\nNegative prompt: blur\nSteps: 20, Sampler: euler"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "prompt-and-parameters", "records": {"parameters": "ignored", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Every sampler branch uses the same prompt pair", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "select-two-identical", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-two-differ", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-two-negative-differs", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"8\", 0], \"latent_image\": [\"5\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-identical-without-negative", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"latent_image\": [\"5\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-one-unresolved", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"missing\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-both-unresolved", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"x\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"y\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Every sampler branch uses the same prompt pair", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "select-three-identical-one-advanced", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-same-text-other-recipe", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"11\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"11\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"fox\", \"prepend_text\": \"a\", \"append_text\": \"\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-multistage-latent", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"3\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-selector-and-plain", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"12\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"12\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"6\", 0], \"on_false\": [\"8\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "select-preview-dropped", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"13\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"14\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"9\", 0]}}, \"15\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"13\", 0]}}, \"16\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"14\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-all-previews-kept", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"13\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"14\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"9\", 0]}}, \"15\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"13\", 0]}}, \"16\": {\"class_type\": \"Image Comparer (rgthree)\", \"inputs\": {\"images\": [\"14\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-preview-and-file", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"13\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"14\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"9\", 0]}}, \"15\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"13\", 0]}}, \"16\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"14\", 0]}}, \"17\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"14\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "select-unconsumed-stage-kept", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"14\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"9\", 0]}}, \"16\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"14\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-preview-unhashable-class", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"14\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"9\", 0]}}, \"16\": {\"class_type\": [\"PreviewImage\"], \"inputs\": {\"images\": [\"14\", 0]}}, \"17\": {\"class_type\": {\"a\": 1}, \"inputs\": {\"images\": [\"3\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "select-preview-through-bad-node", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"13\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"15\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"13\", 0]}}, \"16\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"9\", 0]}}, \"18\": \"not a node\", \"19\": {\"class_type\": \"Note\", \"inputs\": {\"x\": [\"18\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "11", "state": "resolved"}}, "name": "select-detailer-same-prompt", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Sampler stages have different prompts", "reason_code": "multistage-differs", "sampler_id": "11", "state": "ambiguous"}}, "name": "select-detailer-differs", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-detailer-and-own-output", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}, \"13\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"10\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected an image link", "reason_code": "malformed", "sampler_id": "11", "state": "unresolved"}}, "name": "select-detailer-image-literal", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": \"not a link\", \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Cyclic sampler stage ancestry", "reason_code": "malformed", "sampler_id": "11", "state": "unresolved"}}, "name": "select-detailer-cycle", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"10\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"11\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Sampler stages have different prompts", "reason_code": "multistage-differs", "sampler_id": "21", "state": "ambiguous"}}, "name": "select-detailer-chain", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"21\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"11\", 0], \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"21\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "21", "state": "resolved"}}, "name": "select-detailer-chain-same", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"21\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"11\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"21\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Sampler stages have different prompts", "reason_code": "multistage-differs", "sampler_id": "11", "state": "ambiguous"}}, "name": "select-detailer-two-upstream", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"9\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"8\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"ImageBlend\", \"inputs\": {\"image1\": [\"13\", 0], \"image2\": [\"14\", 0]}}, \"13\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"14\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"9\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (MysterySampler).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (MysterySampler).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "MysterySampler", "id": "10"}, "reason": "Unsupported sampler stage ancestry", "reason_code": "unsupported-node", "sampler_id": "11", "state": "unresolved"}}, "name": "select-detailer-unsupported-stage", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"10\": {\"class_type\": \"MysterySampler\", \"inputs\": {\"positive\": [\"6\", 0], \"model\": [\"4\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "11", "state": "unresolved"}}, "name": "select-detailer-upstream-unresolved", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"gone\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Selector branches have different prompts", "reason_code": null, "sampler_id": "11", "state": "ambiguous"}}, "name": "select-detailer-upstream-selector", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"15\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"15\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"6\", 0], \"on_false\": [\"8\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (FaceDetailer).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (FaceDetailer).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FaceDetailer", "id": "11"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "11", "state": "unresolved"}}, "name": "select-detailer-wildcard", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"wildcard\": \"[x|y]\"}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-detailer-no-upscaled-image", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"10\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"11\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "blurry"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "11", "state": "resolved"}}, "name": "select-detailer-no-sampler-upstream", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"10\": {\"class_type\": \"LoadImage\", \"inputs\": {\"image\": \"a.png\"}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-detailer-deep-ancestry", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"d0\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"d1\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d0\", 0]}}, \"d2\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d1\", 0]}}, \"d3\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d2\", 0]}}, \"d4\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d3\", 0]}}, \"d5\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d4\", 0]}}, \"d6\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d5\", 0]}}, \"d7\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d6\", 0]}}, \"d8\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d7\", 0]}}, \"d9\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d8\", 0]}}, \"d10\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d9\", 0]}}, \"d11\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d10\", 0]}}, \"d12\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d11\", 0]}}, \"d13\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d12\", 0]}}, \"d14\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d13\", 0]}}, \"d15\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d14\", 0]}}, \"d16\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d15\", 0]}}, \"d17\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d16\", 0]}}, \"d18\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d17\", 0]}}, \"d19\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d18\", 0]}}, \"d20\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d19\", 0]}}, \"d21\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d20\", 0]}}, \"d22\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d21\", 0]}}, \"d23\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d22\", 0]}}, \"d24\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d23\", 0]}}, \"d25\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d24\", 0]}}, \"d26\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d25\", 0]}}, \"d27\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d26\", 0]}}, \"d28\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d27\", 0]}}, \"d29\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d28\", 0]}}, \"d30\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d29\", 0]}}, \"d31\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d30\", 0]}}, \"d32\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d31\", 0]}}, \"d33\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d32\", 0]}}, \"d34\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d33\", 0]}}, \"d35\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d34\", 0]}}, \"d36\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d35\", 0]}}, \"d37\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d36\", 0]}}, \"d38\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d37\", 0]}}, \"d39\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d38\", 0]}}, \"d40\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d39\", 0]}}, \"d41\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d40\", 0]}}, \"d42\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d41\", 0]}}, \"d43\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d42\", 0]}}, \"d44\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d43\", 0]}}, \"d45\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d44\", 0]}}, \"d46\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d45\", 0]}}, \"d47\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d46\", 0]}}, \"d48\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d47\", 0]}}, \"d49\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d48\", 0]}}, \"d50\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d49\", 0]}}, \"d51\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d50\", 0]}}, \"d52\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d51\", 0]}}, \"d53\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d52\", 0]}}, \"d54\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d53\", 0]}}, \"d55\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d54\", 0]}}, \"d56\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d55\", 0]}}, \"d57\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d56\", 0]}}, \"d58\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d57\", 0]}}, \"d59\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d58\", 0]}}, \"d60\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d59\", 0]}}, \"d61\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d60\", 0]}}, \"d62\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d61\", 0]}}, \"d63\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d62\", 0]}}, \"d64\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d63\", 0]}}, \"d65\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d64\", 0]}}, \"d66\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d65\", 0]}}, \"d67\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d66\", 0]}}, \"d68\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d67\", 0]}}, \"d69\": {\"class_type\": \"ImageScale\", \"inputs\": {\"image\": [\"d68\", 0]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"d69\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"11\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt exceeds inspection limits.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt exceeds inspection limits.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Resolution depth limit reached", "reason_code": "depth-limit", "sampler_id": "s66", "state": "unresolved"}}, "name": "select-detailer-stacked-past-depth", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0], \"latent_image\": [\"5\", 0]}}, \"s0\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"3\", 0]}}, \"s1\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s0\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s2\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s1\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s3\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s2\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s4\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s3\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s5\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s4\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s6\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s5\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s7\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s6\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s8\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s7\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s9\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s8\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s10\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s9\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s10\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s12\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s11\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s13\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s12\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s14\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s13\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s15\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s14\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s16\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s15\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s17\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s16\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s18\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s17\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s19\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s18\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s20\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s19\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s21\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s20\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s22\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s21\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s23\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s22\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s24\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s23\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s25\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s24\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s26\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s25\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s27\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s26\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s28\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s27\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s29\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s28\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s30\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s29\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s31\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s30\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s32\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s31\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s33\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s32\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s34\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s33\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s35\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s34\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s36\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s35\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s37\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s36\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s38\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s37\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s39\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s38\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s40\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s39\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s41\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s40\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s42\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s41\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s43\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s42\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s44\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s43\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s45\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s44\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s46\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s45\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s47\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s46\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s48\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s47\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s49\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s48\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s50\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s49\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s51\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s50\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s52\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s51\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s53\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s52\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s54\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s53\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s55\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s54\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s56\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s55\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s57\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s56\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s58\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s57\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s59\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s58\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s60\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s59\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s61\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s60\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s62\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s61\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s63\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s62\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s64\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s63\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s65\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s64\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"s66\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"s65\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"s66\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Cyclic sampler stage ancestry", "reason_code": "malformed", "sampler_id": "21", "state": "unresolved"}}, "name": "select-detailer-mutual-cycle", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"6\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a fox\", \"clip\": [\"4\", 1]}}, \"7\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"blurry\", \"clip\": [\"4\", 1]}}, \"8\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a cat\", \"clip\": [\"4\", 1]}}, \"11\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"21\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"21\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"11\", 0], \"model\": [\"4\", 0], \"positive\": [\"6\", 0], \"negative\": [\"7\", 0]}}, \"12\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"21\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "embedded-parameters", "status": "resolved", "text": "blur"}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "parameters-basic", "records": {"parameters": "a fox\nNegative prompt: blur\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-no-negative", "records": {"parameters": "a fox\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple negative prompt delimiters", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "parameters-two-delimiters", "records": {"parameters": "a\nNegative prompt: b\nNegative prompt: c\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": null, "state": "unresolved"}}, "name": "parameters-leading-delimiter", "records": {"parameters": "Negative prompt: blur\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": null, "state": "unresolved"}}, "name": "parameters-blank-positive", "records": {"parameters": " …\nNegative prompt: blur\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-footer-not-last", "records": {"parameters": "a fox\nSteps: 20, Sampler: euler, CFG scale: 7\nmore text"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-two-footers", "records": {"parameters": "a\nSteps: 20, Sampler: euler, CFG scale: 7\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"source": "embedded-parameters", "status": "resolved", "text": "blur"}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "parameters-bare-footer", "records": {"parameters": "a fox\nNegative prompt: blur\nSteps: 20"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox\nSteps: 5"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-bare-and-full", "records": {"parameters": "a fox\nSteps: 5\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-two-bare", "records": {"parameters": "a\nSteps: 1\nSteps: 2"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-template", "records": {"parameters": "a fox\nSteps: 20, Sampler: euler, CFG scale: 7\nTemplate: {a|b}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-both-templates", "records": {"parameters": "a\nSteps: 20, Sampler: euler, CFG scale: 7\nTemplate: x\nNegative Template: y"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-templates-reversed", "records": {"parameters": "a\nSteps: 20, Sampler: euler, CFG scale: 7\nNegative Template: y\nTemplate: x"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-two-templates", "records": {"parameters": "a\nSteps: 20, Sampler: euler, CFG scale: 7\nTemplate: x\nTemplate: y"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-template-multiline", "records": {"parameters": "a\nSteps: 20, Sampler: euler, CFG scale: 7\nTemplate: x\nmore"}}, {"evidence": {"prompts": {"negative": {"source": "embedded-parameters", "status": "resolved", "text": "blur"}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "parameters-crlf", "records": {"parameters": "a fox\r\nNegative prompt: blur\r\nSteps: 20, Sampler: euler, CFG scale: 7\r\n"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-cr-only", "records": {"parameters": "a fox\rNegative prompt: blur\rSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-cr-template", "records": {"parameters": "a\nSteps: 20, Sampler: euler, CFG scale: 7\rTemplate: x"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-line-separator", "records": {"parameters": "a fox
Steps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-next-line", "records": {"parameters": "a fox…Steps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-spaced-steps", "records": {"parameters": "a fox\nSteps:\n 20 \n, x"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-steps-newline-bare", "records": {"parameters": "a fox\nSteps:\n20\n"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-arabic-digits", "records": {"parameters": "a fox\nSteps: ٢٠, Sampler: euler"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "Negative prompt delimiter is absent", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-fullwidth-digits", "records": {"parameters": "a fox\nSteps: 2, x"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "parameters-no-digits", "records": {"parameters": "a fox\nSteps: , x"}}, {"evidence": {"prompts": {"negative": {"source": "embedded-parameters", "status": "resolved", "text": "blur"}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "parameters-trailing-spaces", "records": {"parameters": "a fox \nNegative prompt: blur \nSteps: 20, Sampler: euler, CFG scale: 7 \n \n"}}, {"evidence": {"prompts": {"negative": {"source": "embedded-parameters", "status": "resolved", "text": ""}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "parameters-empty-negative", "records": {"parameters": "a fox\nNegative prompt:\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": null, "status": "absent", "text": null}}, "resolution": {"node": null, "reason": "No A1111 parameters", "reason_code": null, "sampler_id": null, "state": "absent"}}, "name": "parameters-empty", "records": {"parameters": ""}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": null, "state": "unresolved"}}, "name": "parameters-only-footer", "records": {"parameters": "Steps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"source": "embedded-parameters", "status": "resolved", "text": "blur"}, "positive": {"source": "embedded-parameters", "status": "resolved", "text": "a fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": null, "state": "resolved"}}, "name": "parameters-with-execution", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {}}", "parameters": "a fox\nNegative prompt: blur\nSteps: 20, Sampler: euler, CFG scale: 7"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "
   café\u001csnow"}}, "resolution": {"node": {"class_type": "ConditioningCombine", "id": "102"}, "reason": "Combined conditioning has different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-0", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"103\": {\"records\": [{\"text\": \"\\u001csnow \", \"negative_text\": \"\\u0085\\u2028 detailed fur\", \"prepend_text\": \"\\u732b\", \"append_text\": \"\\ud83d\\ude00\", \"positive_text\": \"snow\\u3000\", \"negative_effective_text\": \"\\u0085\\u2028 detailed fur\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"
  \", \"prepend_text\": \"\\u001c…\", \"append_text\": \"\\ncafé\\u001csnow\", \"clip\": [\"4\", 1]}}, \"103\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001csnow \", \"negative_text\": \"…
 detailed fur\", \"prepend_text\": \"…猫
 \", \"append_text\": \"
 😀\"}}, \"105\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"…snow\\n\", \"prepend_text\": \"\\n猫\\t\", \"negative_text\": \"snow \"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"104\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "zeroed-conditioning", "status": "resolved", "text": ""}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "猫, snow"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-1", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\u001csnow
 \", \"prepend_text\": \"
 猫
 \", \"negative_text\": \"snow \"}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001c café\", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"105\", 0]}}, \"103\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"103\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-2", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \" a, \"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"103\": {\"class_type\": \"TextInput\", \"inputs\": {\"text\": [\"104\", 0]}}, \"102\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": [\"103\", 0]}}, \"101\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"102\", 0], \"text_l\": \"\"}}, \"108\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t猫\", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"snow\\n\"}}, \"107\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"108\", 0], \"on_false\": [\"109\", 0]}}, \"111\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"…snow\", \"text_l\": \"…snow\"}}, \"110\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"111\", 0]}}, \"106\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"107\", 0], \"on_false\": [\"110\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "café, 😀"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "café, snow\u001c \tfox
  猫"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-3", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\nsnow\\u001c\", \"string_b\": \"\\tfox\\u2028 \", \"delimiter\": \" \"}}, \"103\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"104\", 0], \"string_b\": \"\\u3000\\u732b\\u001c\", \"delimiter\": \" \"}}, \"102\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\ufeffcaf\\u00e9\\n\", \"negative_text\": \"caf\\u00e9\\t\"}}, \"106\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\u3000\\ud83d\\ude00\\u0085\", \"prepend_text\": \"\\u001ccaf\\u00e9\\u2028 \", \"negative_text\": \"\\ufeffsnow\\u0085\"}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-4", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConcatenate\"}, \"105\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \"\\t\\u2028 \", \"text_b\": \"\\u2028 fox\", \"clean_whitespace\": \"false\"}}, \"106\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\nsnow\\t\"}}, \"103\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": [\"104\", 0], \"text_b\": [\"105\", 0], \"text_d\": [\"106\", 0], \"clean_whitespace\": \"false\"}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\u3000a,fox\", \"negative_text\": \"\\u2028 snow\\n\\u732b\"}}, \"110\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": \"\\u001c \"}}, \"109\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"110\", 0], \"text_l\": [\"110\", 0]}}, \"108\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"109\", 0]}}, \"111\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \" caf\\u00e9\\u001c\"}}, \"107\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"108\", 0], \"conditioning_2\": [\"111\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Selector branches have different prompts", "reason_code": null, "sampler_id": "3", "state": "ambiguous"}}, "name": "fuzz-0-5", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"112\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\ufeffdetailed fur\\u0085\", \"prepend_text\": \"\\t\\u732b\\u3000\", \"append_text\": \"caf\\u00e9\\ta,\"}}, \"103\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"104\", 0], \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"107\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001ccaf\\u00e9\\t\", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u0085detailed fur\\u2028 snow\", \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"109\", -1], \"conditioning_2\": [\"109\", -1]}}, \"106\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"107\", 0], \"on_false\": [\"108\", 0]}}, \"111\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001ccaf\\u00e9\\u2028 \", \"clip\": [\"4\", 1]}}, \"110\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"111\", 0]}}, \"105\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"106\", 0], \"on_false\": [\"110\", 0]}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"102\", 0], \"on_false\": [\"105\", 0]}}, \"113\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\ufeff\\u0085\", \"prepend_text\": \"\\u0085snow\\ufeff\", \"append_text\": \"\\u3000fox\\u001c\", \"clip\": [\"4\", 1]}}, \"114\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\tdetailed fur snow\"}}, \"112\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"113\", 0], \"on_false\": [\"114\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "a, 猫\t"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "…猫\u001c"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-6", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ufeff\\n\", \"negative_text\": \"\\u0085\\u732b\\u001c\", \"prepend_text\": \"\\tdetailed fur\\n\", \"append_text\": \" fox\\u2028 \"}}, \"102\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\u732b\\t\", \"prepend_text\": \"\\u3000a,\\u2028 \", \"append_text\": \" \\t\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "😀"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "\n猫"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-7", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"…\", \"negative_text\": \"\\n猫\", \"prepend_text\": \"…a,\", \"append_text\": \"\\u001ccafé \"}}, \"103\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"😀\"}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"103\", 0], \"text_l\": [\"103\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "101"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-8", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"…detailed fur
 \"}}, \"102\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \" 猫\\u001c\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "fox, snow  detailed fur café"}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-9", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"…snow\", \"string_3\": \" detailed fur café\", \"inputcount\": 3, \"delimiter\": \" \", \"return_list\": false}}, \"103\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"103\", 0], \"strip_newlines\": false}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"fox\", \"negative_text\": \"snow\\t\"}}, \"106\": {\"class_type\": \"TextInput\"}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"106\", 0], \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "101"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-10", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\ndetailed fur\\ufefffox\"}}, \"105\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"detailed fur\\ufeff\", \"strip_newlines\": true}}, \"104\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": [\"105\", 0]}}, \"107\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\u001cfox\\u2028 \"}}, \"108\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\nsnow\\u2028 \", \"strip_newlines\": false}}, \"106\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"107\", 0], \"string_b\": [\"108\", 0], \"delimiter\": \" \"}}, \"103\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": [\"104\", 0], \"string_2\": [\"106\", 0], \"inputcount\": 2, \"delimiter\": \",\", \"return_list\": false}}, \"102\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"103\", 0], \"prepend_text\": \"\\tdetailed fur\\u3000\", \"negative_text\": \" detailed fur caf\\u00e9\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Cyclic prompt graph", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-11", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\u0085snow \", \"string_b\": \"a,\\u0085\\u732b\", \"delimiter\": \", \"}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": [\"102\", 0]}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \" caf\\u00e9\\nsnow\", \"negative_text\": \"\\ud83d\\ude00\\u0085\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-12", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"PrimitiveString\"}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"103\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"104\", 0], \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"102\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-13", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\"}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\ncaf\\u00e9\\u001c\", \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"caf\\u00e9\", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"105\", 0], \"on_false\": [\"106\", 0]}}, \"103\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"110\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\tsnow\\u001ccaf\\u00e9\", \"string_b\": \"\\ufeffdetailed fur\\t\", \"delimiter\": \", \"}}, \"109\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_d\": \"\\ufeffa,\\u2028 detailed fur\", \"text_b\": \"\\u0085\\n\", \"text_c\": [\"110\", 0], \"clean_whitespace\": \"true\"}}, \"108\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"109\", 0], \"prepend_text\": \"\\n\\u0085\", \"append_text\": \"\\ta,\\ufeff\", \"clip\": [\"4\", 1]}}, \"107\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"108\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-14", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\"}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\u001csnow\\u001c\", \"prepend_text\": \"\\tdetailed fur\\ufeff\", \"negative_text\": \"\\ndetailed fur\\u001c\"}}, \"103\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\ud83d\\ude00\\u3000\"}}, \"104\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\u001ca,\\u001c\", \"prepend_text\": \"\\nsnow\\ud83d\\ude00\", \"append_text\": \"\\u001ca, \", \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"104\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "ConditioningCombine", "id": "101"}, "reason": "Combined conditioning has different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-15", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"103\": {\"records\": [{\"text\": \"\\u2028 \\u732b\\u2028 detailed fur\", \"negative_text\": \"\\u001c\\ud83d\\ude00\\ufeff\", \"prepend_text\": \"caf\\u00e9\", \"append_text\": \"detailed fur\\ufeff\\ud83d\\ude00\", \"positive_text\": \"\\ufeffdetailed fur\\n\", \"negative_effective_text\": \"\\u001c\\ud83d\\ude00\\ufeff\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u2028 \\u732b\\u2028 detailed fur\", \"negative_text\": \"\\u001c\\ud83d\\ude00\\ufeff\", \"prepend_text\": \"\\tcaf\\u00e9 \", \"append_text\": \"\\u3000detailed fur\\ufeff\\ud83d\\ude00\"}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"103\", 0]}}, \"104\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t\", \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"104\", 0]}}, \"108\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\u3000fox\\u0085fox\", \"string_b\": \"\\u001c\\ud83d\\ude00\\n\\ud83d\\ude00\", \"delimiter\": \"\"}}, \"107\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"108\", 0], \"string_b\": \"\\ufeffa,\\u3000detailed fur\", \"delimiter\": \" \"}}, \"106\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"107\", 0], \"prepend_text\": \"\\u3000caf\\u00e9\\ufeff\", \"append_text\": \"\\ta,\\tcaf\\u00e9\", \"clip\": [\"4\", 1]}}, \"110\": {\"class_type\": \"TextInput\", \"inputs\": {\"text\": \"\\n\\u732b\\ufeff\"}}, \"109\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"110\", 0], \"prepend_text\": \"detailed fursnow\", \"negative_text\": \"\\ta,\"}}, \"105\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"106\", 0], \"on_false\": [\"109\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (Unknown).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (Unknown).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "Unknown", "id": "104"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-16", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"Unknown\", \"inputs\": {\"string_1\": \" \", \"string_2\": \"
 detailed fur\", \"string_3\": \"\\na,\\u001cfox\", \"inputcount\": 3, \"delimiter\": \" \", \"return_list\": false}}, \"103\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"104\", 0], \"text_l\": [\"104\", 0]}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"102\", 0]}}, \"106\": {\"class_type\": \"StringConstant\", \"inputs\": {\"text\": \" snow…\"}}, \"105\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"106\", 0], \"prepend_text\": \"a,\\u001cfox\", \"append_text\": \"\\na, a,\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "ConditioningCombine", "id": "102"}, "reason": "Combined conditioning has different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-17", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"103\": {\"records\": [{\"text\": \"\\u001c\\u0085\", \"negative_text\": \"\\nfox\\u001c\", \"prepend_text\": \"fox\\ufeff\", \"append_text\": \"\\ufefffox\", \"positive_text\": \" snow caf\\u00e9\", \"negative_effective_text\": \"\\nfox\\u001c\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001c\\u0085\", \"negative_text\": \"\\nfox\\u001c\", \"prepend_text\": \" fox\\ufeff\", \"append_text\": \"\\ufefffox\\u3000\"}}, \"105\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": \"\\n\\n\\ud83d\\ude00\"}}, \"104\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"105\", 0], \"prepend_text\": \"\\u0085a,\\u3000\\ud83d\\ude00\", \"negative_text\": \"\\u2028 \\u732b\\u001c\"}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 1], \"conditioning_2\": [\"104\", 0]}}, \"106\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"snow detailed fur\", \"prepend_text\": \"\\n\\u732b\\u001c\", \"negative_text\": \"detailed fur\\ud83d\\ude00\"}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0]}}, \"109\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\n\\u732b \"}}, \"110\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\na,\\ufeffcaf\\u00e9\"}}, \"108\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"109\", 0], \"on_false\": [\"110\", 0]}}, \"107\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"108\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "101"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-18", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\tdetailed fur\\t\"}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\n\\ncaf\\u00e9\", \"text_l\": \"\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a, detailed fur, café"}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "105"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-19", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\ncafé\", \"prepend_text\": \"a, detailed fur\", \"negative_text\": \"\\na,\\u001c\"}}, \"104\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"…猫…\", \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"103\", 0], \"on_false\": [\"104\", 0]}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"105\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u001ca,\\t\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "101"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-20", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u0085fox\\ufeff\"}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u0085snow\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-21", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\u001ccaf\\u00e9\\u0085\", \"prepend_text\": \"\\u3000detailed fur\", \"negative_text\": \"\\u001c\"}}, \"101\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"103\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\tcaf\\u00e9 \", \"prepend_text\": \"\\t\\u732b\", \"append_text\": \"\\tcaf\\u00e9 \", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "101"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-22", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\tfox\\u001c\"}}, \"103\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\u001ccaf\\u00e9\\ufeffa,\"}}, \"102\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"103\", 0], \"prepend_text\": \"\\tdetailed fur\\u0085\", \"append_text\": \"\\u3000fox\\u001c\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "\u001c😀…"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "foxfox, \u001c猫
 "}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-23", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\ufefffoxfox\", \"string_b\": \"\\u001c\\u732b\\u2028 \", \"delimiter\": \", \"}}, \"102\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": [\"103\", 0], \"inputcount\": 1, \"delimiter\": \",\", \"return_list\": false}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\tcaf\\u00e9\\u0085\"}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}, \"110\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\u001c\\ud83d\\ude00\\u0085\"}}, \"109\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"110\", 0]}}, \"108\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"109\", 0]}}, \"107\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"108\", 0], \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"105\", 0], \"on_false\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-24", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\u001c\"}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"103\", 0], \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"104\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001ccafé
 café\", \"negative_text\": \" detailed fur 😀\", \"prepend_text\": \"detailed fur\\u001c\", \"append_text\": \"
 a,…detailed fur\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "102"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-25", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"…\"}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t猫…\", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"105\", 0]}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-26", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\tdetailed fur \", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"105\", 0], \"conditioning_2\": [\"105\", 0]}}, \"103\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"106\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ncaf\\u00e9\\ufeff\", \"negative_text\": \"\\u3000detailed fur\\u001ca,\", \"prepend_text\": \"\\u0085snow\\u001cfox\", \"append_text\": \"\\u001c\\u732b\\u3000\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-27", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"a, \"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"103\": {\"class_type\": \"Text Concatenate\", \"inputs\": []}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\tdetailed fur\\u001c\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-28", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\"}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"
 detailed fur\\t\", \"negative_text\": \" snow
 😀\", \"prepend_text\": \"\\n😀…\", \"append_text\": \"\\u001c😀
 \"}}, \"102\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\tfox…\", \"prepend_text\": \" 猫\", \"negative_text\": \"café…\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-29", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"snow \", \"negative_text\": \"\\u0085\\u0085\", \"prepend_text\": \"\\u2028 a, fox\", \"append_text\": \"\\tcaf\\u00e9\"}}, \"102\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u001cdetailed fur\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "fox…detailed fur \u001c猫 snow a,"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a,\u001c"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-30", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"a,\\u001c\", \"text_l\": \"a,\\u001c\"}}, \"102\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u001c猫 snow\", \"prepend_text\": \" fox…detailed fur\", \"append_text\": \"a,\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-31", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\u0085a, \", \"string_b\": \"caf\\u00e9\\u2028 \", \"delimiter\": \", \"}}, \"105\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\u0085caf\\u00e9\\u2028 \"}}, \"103\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"104\", 0], \"string_b\": [\"105\", 0], \"delimiter\": \"\"}}, \"102\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": [\"103\", 0]}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\tcaf\\u00e9\\n\", \"negative_text\": \"\\u0085fox\\ufeff\"}}, \"106\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u001ca,\\t\", \"prepend_text\": \"\\u0085\\u732b\\t\", \"append_text\": \"\\ufeffa,\\t\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "foxsnow"}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "105"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-32", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \"…foxsnow\", \"clean_whitespace\": true}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"103\", 0], \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"105\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"detailed fur \"}}, \"104\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"105\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "fox fox 猫 café…fox …a,\t fox café\ta, snow"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "snow, fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-33", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"103\": {\"records\": [{\"text\": \" caf\\u00e9\\u3000!\", \"negative_text\": \"\\u0085snow\\u3000\", \"prepend_text\": \"detailed fur\", \"append_text\": \"\", \"positive_text\": \"\\u001c\\ud83d\\ude00\\u2028 \", \"negative_effective_text\": \"\\u0085snow\\u3000\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" café \", \"negative_text\": \"…snow \", \"prepend_text\": \"\\n detailed fur\", \"append_text\": \"\\n \"}}, \"105\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\u001cfox…\", \"prepend_text\": \" snow
 \", \"negative_text\": \"café detailed fur\"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"102\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"103\", 1], \"on_false\": [\"104\", 0]}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"109\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": \"…a,\\t\", \"text_d\": \"fox\\n\", \"text_a\": \"\\u001ccafé…fox\", \"clean_whitespace\": \"false\"}}, \"108\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": [\"109\", 0], \"clean_whitespace\": true}}, \"107\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": [\"108\", 0], \"prepend_text\": \" fox 猫\", \"append_text\": \"…café\\ta,\"}}, \"106\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"107\", 0], \"prepend_text\": \"\\tfox \", \"append_text\": \"snow \", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-34", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"111\": {\"records\": [{\"text\": \"\\nsnow\\u001c\", \"negative_text\": \"\\tdetailed fur \", \"prepend_text\": \"snow\", \"append_text\": \"\\ufeffa,\", \"positive_text\": \"\\u001c\\n\", \"negative_effective_text\": \"\\tdetailed fur \"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\nfox\\u2028 \", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"105\", 0]}}, \"103\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"109\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\ta,\\u2028 \", \"prepend_text\": \"\\u2028 caf\\u00e9\\u3000\", \"append_text\": \"\\u2028 \\ud83d\\ude00\\n\", \"clip\": [\"4\", 1]}}, \"110\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\u3000\\u2028 \", \"prepend_text\": \"\\u3000detailed fur \", \"append_text\": \"\\tcaf\\u00e9\", \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"109\", 0], \"on_false\": [\"110\", 0]}}, \"111\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\nsnow\\u001c\", \"negative_text\": \"\\tdetailed fur \", \"prepend_text\": \"snow\\u0085\", \"append_text\": \"\\ufeffa, \"}}, \"107\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"108\", 0], \"conditioning_2\": [\"111\", 0]}}, \"106\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "\t😀\t"}, "positive": {"source": "execution", "status": "resolved", "text": "fox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-35", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"101\": {\"records\": [{\"text\": \"caf\\u00e9\\u2028 \", \"negative_text\": \"\\n\\u3000caf\\u00e9\", \"prepend_text\": \"caf\\u00e9\\ufeff\", \"append_text\": \"snow\", \"positive_text\": \"\\ufefffox\\ufeff\", \"negative_effective_text\": \"\\n\\u3000caf\\u00e9\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"caf\\u00e9\\u2028 \", \"negative_text\": \"\\n\\u3000caf\\u00e9\", \"prepend_text\": \"\\u3000caf\\u00e9\\ufeff\", \"append_text\": \"\\u3000snow\\u3000\"}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ufeff\\ud83d\\ude00\\ta,\", \"negative_text\": \"\\t\\ud83d\\ude00\\t\", \"prepend_text\": \" \\u3000\", \"append_text\": \"\\u3000snow\\u001c\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "CLIPTextEncodeSDXL", "id": "101"}, "reason": "Encoder parts have different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-36", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"café
 fox\", \"text_l\": \"
 \"}}, \"103\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\n猫\"}}, \"107\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"…\", \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"107\", 0]}}, \"109\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" 😀 a,\", \"clip\": [\"4\", 1]}}, \"110\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" café\\n猫\", \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"109\", 0], \"on_false\": [\"110\", 0]}}, \"105\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"106\", 0], \"conditioning_2\": [\"108\", 0]}}, \"111\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\tsnow \", \"prepend_text\": \"猫…\", \"negative_text\": \"…detailed fur\\u001c\"}}, \"104\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"105\", 0], \"conditioning_2\": [\"111\", 0]}}, \"102\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"103\", 0], \"on_false\": [\"104\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "…猫\t"}}, "resolution": {"node": null, "reason": "Execution evidence does not match recorded node inputs", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-37", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"104\": {\"records\": [{\"text\": \"\\ndetailed fur\\u2028 !\", \"negative_text\": \"\\na,\\u2028 \", \"prepend_text\": \"\", \"append_text\": \"detailed fur\", \"positive_text\": \" \\ud83d\\ude00\\n\", \"negative_effective_text\": \"\\na,\\u2028 \"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 1], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": null, \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\u0085\\u732b\\t\", \"inputcount\": 1, \"delimiter\": \",\", \"return_list\": false}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"103\", 0], \"text_l\": [\"103\", 0]}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"102\", 0]}}, \"104\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ndetailed fur\\u2028 \", \"negative_text\": \"\\na,\\u2028 \", \"prepend_text\": \" \\u0085\", \"append_text\": \"\\ndetailed fur\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "
 fox\t猫"}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-38", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u2028 fox\\t\\u732b\", \"clip\": [\"4\", 1]}}, \"105\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": \"\\u3000\\u732b\\u3000\"}}, \"104\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"105\", 0], \"strip_newlines\": true}}, \"103\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": [\"104\", 0]}}, \"102\": {\"class_type\": \"PromptManagerV2\"}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (Unknown).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "
 snow
 \t"}}, "resolution": {"node": {"class_type": "Unknown", "id": "105"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-39", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\u2028 snow\\u2028 \"}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": [\"103\", 0], \"text_c\": \"\\ufeff\\t\", \"clean_whitespace\": \"false\"}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\ufeff\\u732b\\u0085\", \"strip_newlines\": false}}, \"107\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"108\", 0]}}, \"106\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"107\", 0], \"prepend_text\": \"\", \"append_text\": \"\\ufeff\\u732b\\u3000\", \"clip\": [\"4\", 1]}}, \"105\": {\"class_type\": \"Unknown\", \"inputs\": {\"conditioning_1\": [\"106\", 0], \"conditioning_2\": [\"106\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Execution evidence does not match recorded node inputs", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-40", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"102\": {\"records\": [{\"text\": \"\\n\\ud83d\\ude00\\u2028 !\", \"negative_text\": \" fox\\t\", \"prepend_text\": \"caf\\u00e9\\ufeff\", \"append_text\": \"detailed fur\\ufeffdetailed fur\", \"positive_text\": \"\\u0085\\u732b\\u0085detailed fur\", \"negative_effective_text\": \" fox\\t\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\n\\ud83d\\ude00\\u2028 \", \"negative_text\": \" fox\\t\", \"prepend_text\": \"\\u0085caf\\u00e9\\ufeff\", \"append_text\": \"\\ndetailed fur\\ufeffdetailed fur\"}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"106\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"fox\", \"strip_newlines\": true}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}, \"104\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"105\", 0]}}, \"103\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \" detailed fur\\u001c\", \"negative_text\": \"\\u0085\\na,\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "101"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-41", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"snow\\tsnow\"}}, \"104\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \" detailed fur \"}}, \"103\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"104\", 0], \"strip_newlines\": true}}, \"102\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"103\", 0], \"prepend_text\": \"\\t\\u001c\", \"append_text\": \"
 snow \", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-42", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"猫\", \"prepend_text\": \"
 a,\\t\", \"append_text\": \" \\u001c\", \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"102\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "café, detailed fur snow a, café \t😀"}, "positive": {"source": "execution", "status": "resolved", "text": "snow "}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "3", "state": "resolved"}}, "name": "fuzz-0-43", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"105\": {\"records\": [{\"text\": \"\\u3000a,\\u3000\", \"negative_text\": \"snow\\u3000\", \"prepend_text\": \"caf\\u00e9detailed fur\", \"append_text\": \"fox\\u001csnow\", \"positive_text\": \"\\u0085\\u732b\\u2028 \", \"negative_effective_text\": \"snow\\u3000\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"café…\", \"text_l\": \"café…\"}}, \"103\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"104\", 0], \"conditioning_2\": [\"104\", 0]}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"105\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" a, \", \"negative_text\": \"snow \", \"prepend_text\": \"\\tcafédetailed fur\", \"append_text\": \"\\nfox\\u001csnow\"}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"102\", 0], \"on_false\": [\"105\", 1]}}, \"109\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \"\\na, \", \"text_c\": \"\\ncafé\\n\", \"clean_whitespace\": true}}, \"108\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \" detailed fur snow\", \"string_2\": [\"109\", 0], \"string_3\": \"\\t😀…\", \"inputcount\": 3, \"delimiter\": \" \", \"return_list\": false}}, \"107\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"108\", 0], \"prepend_text\": \"…café\\u001c\", \"negative_text\": \"snow…\"}}, \"106\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "😀 😀"}}, "resolution": {"node": null, "reason": "Negative input is absent", "reason_code": null, "sampler_id": "3", "state": "absent"}}, "name": "fuzz-0-44", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\ud83d\\ude00 \\ud83d\\ude00\", \"clip\": [\"4\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "café\u001cdetailed fur, detailed fur"}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-45", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"106\": {\"records\": [{\"text\": \"\\u001cfox\\u3000!\", \"negative_text\": \"\\n\\ud83d\\ude00\\u0085\", \"prepend_text\": \"\\ufeff\", \"append_text\": \"a,\", \"positive_text\": \"\\ufeffdetailed fur\\ud83d\\ude00\", \"negative_effective_text\": \"\\n\\ud83d\\ude00\\u0085\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"
 detailed fur \", \"prepend_text\": \"…café\\u001cdetailed fur\", \"negative_text\": \"\\u001cfox\"}}, \"105\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"
 😀\"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"103\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": []}, \"106\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001cfox \", \"negative_text\": \"\\n😀…\", \"prepend_text\": \"
 \", \"append_text\": \" a,\\t\"}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"106\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "CLIPTextEncodeSDXL", "id": "102"}, "reason": "Encoder parts have different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-46", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"106\": {\"records\": [{\"text\": \"\\t\\u732b\\u2028 \", \"negative_text\": \"\\u001cfox\\ufeff\", \"prepend_text\": \"fox\\u3000detailed fur\", \"append_text\": \"detailed fur\", \"positive_text\": \" fox \\u732b\", \"negative_effective_text\": \"\\u001cfox\\ufeff\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \" detailed fur\", \"prepend_text\": \"café
 \", \"append_text\": \"\\ncafé\\n\"}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"103\", 0], \"text_l\": \"\\t😀
 猫\"}}, \"106\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\t猫
 \", \"negative_text\": \"\\u001cfox\", \"prepend_text\": \"\\nfox detailed fur\", \"append_text\": \"\\ndetailed fur
 \"}}, \"105\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"106\", 0]}}, \"104\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"105\", 0]}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"102\", 0], \"on_false\": [\"104\", 0]}}, \"110\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \"fox
 \", \"text_c\": \"猫\", \"text_a\": \"\\t😀\", \"clean_whitespace\": \"false\"}}, \"109\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": [\"110\", 0], \"inputcount\": 1, \"delimiter\": \",\", \"return_list\": false}}, \"108\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"109\", 0], \"prepend_text\": \"\\u001c😀\\t猫\", \"append_text\": \" a,\", \"clip\": [\"4\", 1]}}, \"107\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"108\", 0], \"conditioning_2\": [\"108\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "102"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-47", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \" detailed fur
 猫\"}}, \"104\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\tcafé
 \", \"prepend_text\": \"
 …😀\", \"append_text\": \"fox\\n\", \"clip\": [\"4\", 1]}}, \"103\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"102\", 0], \"on_false\": [\"103\", 0]}}, \"105\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \" 😀\", \"text_l\": \" 😀\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Missing or malformed graph node", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-48", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": []}, \"101\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\u001cfoxcafé\"}}, \"106\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \" detailed fur \"}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}, \"104\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"105\", 0], \"prepend_text\": \"\\tfox
 猫\", \"append_text\": \" 猫…café\", \"clip\": [\"4\", 1]}}, \"103\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"103\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "café
 😀"}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "102"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-49", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"café
 😀\", \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"a,\\t\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "😀"}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "105"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-50", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \" \\t\"}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\u2028 \\ud83d\\ude00\\u2028 \", \"negative_text\": \"\\ufeffdetailed fur\\t\"}}, \"105\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \" caf\\u00e9\\ufeffsnow\"}}, \"104\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"105\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "ConditioningCombine", "id": "101"}, "reason": "Combined conditioning has different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-51", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"105\": {\"records\": [{\"text\": \"\\ufeffcaf\\u00e9\\u2028 \", \"negative_text\": \"\\t\\u732b\\t\", \"prepend_text\": \"\\ufeff\\ud83d\\ude00\\u001cdetailed fur\", \"append_text\": \"fox\", \"positive_text\": \"\\ud83d\\ude00\\t\", \"negative_effective_text\": \"\\t\\u732b\\t\"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"a,\\tdetailed fur\", \"prepend_text\": \"\\nfox\\n\", \"append_text\": \"fox\\u3000\\ud83d\\ude00\"}}, \"103\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"caf\\u00e9 \", \"string_b\": [\"104\", 0], \"delimiter\": \", \"}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"103\", 0], \"text_l\": [\"103\", 0]}}, \"105\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ufeffcaf\\u00e9\\u2028 \", \"negative_text\": \"\\t\\u732b\\t\", \"prepend_text\": \"\\ufeff\\ud83d\\ude00\\u001cdetailed fur\", \"append_text\": \"fox\\u2028 \"}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"105\", 0]}}, \"109\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \" a,\\na,\", \"string_b\": \"\\ufeff\\u2028 \", \"delimiter\": \"\"}}, \"108\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"109\", 0]}}, \"107\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": [\"108\", 0]}}, \"106\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"107\", 0], \"text_l\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "fox, a,"}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "103"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-52", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\"}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \" a,\\t\", \"strip_newlines\": true}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\tfox \", \"negative_text\": \" snow
 😀\"}}, \"103\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \" a,\"}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Selector branches have different prompts", "reason_code": null, "sampler_id": "3", "state": "ambiguous"}}, "name": "fuzz-0-53", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\nsnow\\ufeffdetailed fur\", \"negative_text\": \"\\nfox\\u2028 \", \"prepend_text\": \"a,\", \"append_text\": \"\\ta,\\u001c\"}}, \"105\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\u0085caf\\u00e9\", \"prepend_text\": \"\\ufeffcaf\\u00e9\\u3000\", \"append_text\": \"\\ufeff\\u732b\"}}, \"104\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"105\", 0], \"strip_newlines\": true}}, \"103\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \"\\ufeffa,\\u0085\", \"append_text\": \"\\tdetailed fur\\u3000detailed fur\", \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"102\", 0], \"on_false\": [\"103\", 0]}}, \"109\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ufeff\\u732b\\u0085\", \"negative_text\": \"\\ta,\\n\\ud83d\\ude00\", \"prepend_text\": \"\\u2028 caf\\u00e9\\u2028 \", \"append_text\": \" \\ufeffcaf\\u00e9\"}}, \"108\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"109\", 1]}}, \"111\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u001cdetailed fur\\u001c\", \"strip_newlines\": false}}, \"110\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"111\", 0], \"text_l\": \"\"}}, \"107\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"108\", 0], \"conditioning_2\": [\"110\", 0]}}, \"106\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Execution evidence does not match recorded node inputs", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-54", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"102\": {\"records\": [{\"text\": \"\\ufeffdetailed fur\\u0085!\", \"negative_text\": \"\\u3000fox \", \"prepend_text\": \"caf\\u00e9\", \"append_text\": \"\", \"positive_text\": \"\\ufeffa,\\n\", \"negative_effective_text\": \"\\u3000fox \"}]}}}", "prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"detailed fur…\", \"negative_text\": \" fox \", \"prepend_text\": \"…café\\u001c\", \"append_text\": \"
 \\u001c\"}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 1], \"conditioning_2\": [\"102\", 1]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "No supported sampler was found.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "No supported sampler was found.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "No supported sampler pair found", "reason_code": "no-sampler", "sampler_id": null, "state": "unresolved"}}, "name": "fuzz-0-55", "records": {"prompt": "{\"3\": {\"class_type\": null, \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"fox \", \"strip_newlines\": false}}, \"103\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"104\", 0], \"string_b\": \"\\u3000caf\\u00e9\\u2028 \", \"delimiter\": \"\"}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\tcaf\\u00e9\\n\\ud83d\\ude00\", \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"109\", 0]}}, \"107\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"108\", 0]}}, \"106\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"107\", 0]}}, \"105\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"106\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "101"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-56", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\t\\u732b\"}}, \"102\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u001csnow\\u001c\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-57", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": []}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u3000caf\\u00e9\\t\"}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"106\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\ufeffa,\\ufeff\\ud83d\\ude00\"}}, \"107\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \" a,\\ufeff\\ud83d\\ude00\"}}, \"105\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"106\", 0], \"on_false\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "CLIPTextEncodeSDXL", "id": "101"}, "reason": "Encoder parts have different texts", "reason_code": "composite", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-58", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": \"😀\"}}, \"103\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_d\": \"
 猫\\t\", \"text_a\": \"…detailed fur
 detailed fur\", \"text_b\": [\"104\", 0], \"clean_whitespace\": true}}, \"106\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": \"
 detailed fur \"}}, \"105\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"106\", 0], \"strip_newlines\": false}}, \"102\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"103\", 0], \"string_b\": [\"105\", 0], \"delimiter\": \" \"}}, \"101\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"102\", 0], \"text_l\": \"猫\\ndetailed fur\"}}, \"107\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"
 猫\\n\", \"negative_text\": \"\\nsnow
 猫\", \"prepend_text\": \"
 detailed fur \", \"append_text\": \"\\u001c\"}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "3", "state": "unresolved"}}, "name": "fuzz-0-59", "records": {"prompt": "{\"3\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\nfox\\t\", \"prepend_text\": \" \\ud83d\\ude00\\u001c\", \"append_text\": \"\\u001csnow \"}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {}}, \"104\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\ncaf\\u00e9\\u3000\"}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "
   café\u001csnow"}}, "resolution": {"node": {"class_type": "ConditioningCombine", "id": "102"}, "reason": "Combined conditioning has different texts", "reason_code": "composite", "sampler_id": "106", "state": "unresolved"}}, "name": "select-fuzz-0-0", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"103\": {\"records\": [{\"text\": \"\\u001csnow \", \"negative_text\": \"\\u0085\\u2028 detailed fur\", \"prepend_text\": \"\\u732b\", \"append_text\": \"\\ud83d\\ude00\", \"positive_text\": \"snow\\u3000\", \"negative_effective_text\": \"\\u0085\\u2028 detailed fur\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u2028 \\u3000\", \"prepend_text\": \"\\u001c\\u0085\", \"append_text\": \"\\ncaf\\u00e9\\u001csnow\", \"clip\": [\"4\", 1]}}, \"103\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001csnow \", \"negative_text\": \"\\u0085\\u2028 detailed fur\", \"prepend_text\": \"\\u0085\\u732b\\u2028 \", \"append_text\": \"\\u2028 \\ud83d\\ude00\"}}, \"105\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\u0085snow\\n\", \"prepend_text\": \"\\n\\u732b\\t\", \"negative_text\": \"\\ufeffsnow \"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"104\", 0]}}, \"106\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"106\", 0]}}, \"108\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-1", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"snow \", \"negative_text\": \"\\n😀\\tcafé\", \"prepend_text\": \"😀café\", \"append_text\": \"\\tfox \"}}, \"106\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \" a, \"}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}, \"104\": {\"class_type\": \"TextInput\", \"inputs\": {\"text\": [\"105\", 0]}}, \"103\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"104\", 0], \"strip_newlines\": false}}, \"102\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"103\", 0], \"prepend_text\": \"\\n猫\", \"append_text\": \" 猫…\", \"clip\": [\"4\", 1]}}, \"107\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"109\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"
 snow猫\", \"strip_newlines\": true}}, \"108\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"109\", 0], \"text_l\": [\"109\", 0]}}, \"110\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"猫\\t\", \"text_l\": \"猫\\t\"}}, \"111\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"108\", 0], \"negative\": [\"110\", 0], \"latent_image\": [\"5\", 0]}}, \"112\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"115\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\u001ca, \", \"string_b\": \" detailed fur\\n\", \"delimiter\": \" \"}}, \"114\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"115\", 0], \"text_l\": [\"115\", 0]}}, \"118\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"café\", \"string_b\": \" 😀…\", \"delimiter\": \" \"}}, \"117\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": [\"118\", 0], \"clean_whitespace\": \"false\"}}, \"116\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"117\", 0], \"clip\": [\"4\", 1]}}, \"113\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"112\", 0], \"model\": [\"4\", 0], \"positive\": [\"114\", 0], \"negative\": [\"116\", 0]}}, \"119\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"113\", 0]}}, \"120\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"113\", 0]}}, \"121\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"111\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "102"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "104", "state": "unresolved"}}, "name": "select-fuzz-0-2", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\t\\ud83d\\ude00\\u3000\"}}, \"103\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\na,\\t\", \"text_l\": \"\\na,\\t\"}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"103\", 0]}}, \"104\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"105\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"106\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"105\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-3", "records": {"parameters": "Steps:٣, a\r\nfox\r"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-4", "records": {"parameters": "Negative prompt: blur \tfox 
 a,
Negative prompt:\n"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-5", "records": {"parameters": "\u001ccafé Negative Template: n\n"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "109"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "111", "state": "unresolved"}}, "name": "select-fuzz-0-6", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"105\": {\"records\": [{\"text\": \"\\u001csnow\\ufeff\", \"negative_text\": \"\\ud83d\\ude00\\t\", \"prepend_text\": \"\\ud83d\\ude00\", \"append_text\": \"detailed fur\", \"positive_text\": \"\\u0085snow\\ufeff\", \"negative_effective_text\": \"\\ud83d\\ude00\\t\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"detailed fur…\"}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": \"fox😀\", \"text_a\": [\"103\", 0], \"text_d\": \" 😀😀\", \"clean_whitespace\": \"false\"}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"…a, \", \"negative_text\": \"fox\\u001c😀\"}}, \"105\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001csnow\", \"negative_text\": \"😀\\t\", \"prepend_text\": \" 😀 \", \"append_text\": \"\\u001cdetailed fur \"}}, \"106\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"109\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \" snow 猫\"}}, \"108\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"109\", 0]}}, \"107\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"108\", 0]}}, \"110\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"
 😀\", \"clip\": [\"4\", 1]}}, \"111\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"107\", 0], \"negative\": [\"110\", 0], \"latent_image\": [\"5\", 0]}}, \"112\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"106\", 0]}}, \"117\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" 猫…fox\", \"clip\": [\"4\", 1]}}, \"116\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"117\", 0]}}, \"115\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"116\", 0]}}, \"118\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \" 😀\\n\", \"prepend_text\": \"\\ncafé detailed fur\", \"negative_text\": \"…café \"}}, \"114\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"115\", 0], \"conditioning_2\": [\"118\", 0]}}, \"121\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"
 …\", \"prepend_text\": \"猫
 \", \"append_text\": \"\\nfox…\", \"clip\": [\"4\", 1]}}, \"120\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"121\", 0]}}, \"119\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"120\", 0]}}, \"113\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"114\", 0], \"negative\": [\"119\", 0], \"upscaled_image\": [\"112\", 0]}}, \"122\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"113\", 0]}}, \"123\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"111\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-7", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"110\": {\"records\": [{\"text\": \"\\u0085snow\\ufeff\", \"negative_text\": \"\\u001cdetailed fur\\u3000\", \"prepend_text\": \"caf\\u00e9\\ta,\", \"append_text\": \"fox\\ufeff\", \"positive_text\": \" caf\\u00e9\\u0085\", \"negative_effective_text\": \"\\u001cdetailed fur\\u3000\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\ncafé\"}}, \"103\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \"a,\\t\", \"negative_text\": \"a,
 \"}}, \"106\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \" 猫\\u001c\", \"string_b\": \"  \", \"delimiter\": \"\"}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"106\", 0], \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"105\", 0]}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"107\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"110\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"…snow\", \"negative_text\": \"\\u001cdetailed fur \", \"prepend_text\": \"café\\ta,\", \"append_text\": \"fox\"}}, \"109\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"110\", 1], \"conditioning_2\": [\"110\", 1]}}, \"108\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"109\", 0]}}, \"111\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\ta, \", \"prepend_text\": \"…猫 \", \"negative_text\": \"snow\"}}, \"112\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"108\", 0], \"negative\": [\"111\", 0], \"latent_image\": [\"5\", 0]}}, \"114\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\tdetailed fur\\u001c\"}}, \"115\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"
 猫\"}}, \"113\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"114\", 0], \"on_false\": [\"115\", 0]}}, \"119\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\u001cfox
 \"}}, \"120\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\nsnow
 \", \"strip_newlines\": false}}, \"118\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"119\", 0], \"string_b\": [\"120\", 0], \"delimiter\": \" \"}}, \"117\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"118\", 0], \"prepend_text\": \"\\u001csnow\\t\", \"negative_text\": \" snow \"}}, \"116\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"117\", 0]}}, \"121\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"113\", 0], \"negative\": [\"116\", 0], \"latent_image\": [\"5\", 0]}}, \"122\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"123\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"122\", 0]}}, \"124\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"122\", 0]}}, \"125\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"112\", 0]}}, \"128\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \" a,\", \"text_l\": \" a,\"}}, \"131\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t猫snow\", \"clip\": [\"4\", 1]}}, \"132\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"😀…\", \"clip\": [\"4\", 1]}}, \"130\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"131\", 0], \"on_false\": [\"132\", 0]}}, \"129\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"130\", 0]}}, \"127\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"128\", 0], \"conditioning_2\": [\"129\", 0]}}, \"126\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"125\", 0], \"model\": [\"4\", 0], \"positive\": [\"113\", 0], \"negative\": [\"127\", 0]}}, \"133\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"126\", 0]}}, \"134\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"121\", 0]}}, \"135\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"134\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-8", "records": {"parameters": "Steps:٣, a
\u001ca,\t\n"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "119"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "117", "state": "unresolved"}}, "name": "select-fuzz-0-9", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"127\": {\"records\": [{\"text\": \"\\u0085\\u3000\", \"negative_text\": \"\\u2028 a,\\ufeff\", \"prepend_text\": \"\", \"append_text\": \"\\u732b\", \"positive_text\": \"snow \", \"negative_effective_text\": \"\\u2028 a,\\ufeff\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"…猫\\n\", \"strip_newlines\": false}}, \"103\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \"…detailed fur\", \"append_text\": \"detailed fur \", \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"101\": {\"class_type\": \"Unknown\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"102\", 0]}}, \"108\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"…😀café\"}}, \"107\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"108\", 0]}}, \"106\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"a,
 detailed fur\", \"string_2\": [\"107\", 0], \"string_3\": \"
 café\", \"inputcount\": 3, \"delimiter\": \" \", \"return_list\": false}}, \"105\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"106\", 0], \"prepend_text\": \" café\\n\", \"append_text\": \"…café…\", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"113\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\u001csnow\\u001c\"}}, \"112\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": [\"113\", 0], \"prepend_text\": \"\\tdetailed fur\", \"append_text\": \"\\ndetailed fur\\u001c\"}}, \"111\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"112\", 0], \"clip\": [\"4\", 1]}}, \"110\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"111\", 0], \"conditioning_2\": [\"111\", 0]}}, \"114\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"😀 \"}}, \"115\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"110\", 0], \"negative\": [\"114\", 0], \"latent_image\": [\"109\", 0]}}, \"116\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"119\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \" fox \"}}, \"118\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"119\", 0], \"conditioning_2\": [\"119\", 0]}}, \"122\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_d\": \"\\u001c😀
 猫\", \"clean_whitespace\": true}}, \"121\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"122\", 0], \"strip_newlines\": true}}, \"120\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"121\", 0], \"text_l\": [\"121\", 0]}}, \"117\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"116\", 0], \"model\": [\"4\", 0], \"positive\": [\"118\", 0], \"negative\": [\"120\", 0]}}, \"123\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"115\", 0]}}, \"125\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\tsnow \"}}, \"127\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"… \", \"negative_text\": \"
 a,\", \"prepend_text\": \"\\u001c\", \"append_text\": \"猫\"}}, \"126\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"127\", 1]}}, \"124\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"125\", 0], \"negative\": [\"126\", 0], \"upscaled_image\": [\"123\", 0]}}, \"128\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"124\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "110", "state": "unresolved"}}, "name": "select-fuzz-0-10", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"113\": {\"records\": [{\"text\": \"\\u0085detailed fur\\ufeffdetailed fur\", \"negative_text\": \"\\ufeff\\u001c\", \"prepend_text\": \"a,\\u001cfox\", \"append_text\": \"a,fox\", \"positive_text\": \"\\u3000\\u732b\\u3000\", \"negative_effective_text\": \"\\ufeff\\u001c\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\nsnow\\u3000\", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"105\", 0], \"conditioning_2\": [\"105\", 0]}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"101\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"106\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\ta,\\tcaf\\u00e9\", \"prepend_text\": \"\\ufeffa,\\u3000\", \"append_text\": \"\\ufeffdetailed fur\\n\", \"clip\": [\"4\", 1]}}, \"107\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"109\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"108\", 0]}}, \"112\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\n\\ud83d\\ude00 \"}}, \"113\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u0085detailed fur\\ufeffdetailed fur\", \"negative_text\": \"\\ufeff\\u001c\", \"prepend_text\": \"\\na,\\u001cfox\", \"append_text\": \"\\ta,fox\"}}, \"111\": {\"class_type\": \"Unknown\", \"inputs\": {\"boolean\": true, \"on_true\": [\"112\", 0], \"on_false\": [\"113\", 1]}}, \"110\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"108\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"111\", 0]}}, \"114\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"110\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-11", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"105\": {\"records\": [{\"text\": \"\\u001c\\u0085\", \"negative_text\": \"\\nfox\\u001c\", \"prepend_text\": \"fox\\ufeff\", \"append_text\": \"\\ufefffox\", \"positive_text\": \" snow caf\\u00e9\", \"negative_effective_text\": \"\\nfox\\u001c\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\na,\\n\", \"strip_newlines\": false}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"105\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001c…\", \"negative_text\": \"\\nfox\\u001c\", \"prepend_text\": \" fox\", \"append_text\": \"fox \"}}, \"107\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": \"\\n\\n😀\"}}, \"106\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"107\", 0], \"prepend_text\": \"…a, 😀\", \"negative_text\": \"
 猫\\u001c\"}}, \"104\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"105\", 1], \"conditioning_2\": [\"106\", 0]}}, \"108\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"snow detailed fur\", \"prepend_text\": \"\\n猫\\u001c\", \"negative_text\": \"detailed fur😀\"}}, \"103\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"104\", 0], \"conditioning_2\": [\"108\", 0]}}, \"109\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"111\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\n猫 \"}}, \"110\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"111\", 0]}}, \"116\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\tcafé\", \"clip\": [\"4\", 0.0]}}, \"115\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"116\", 0]}}, \"114\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"115\", 0], \"conditioning_2\": [\"115\", 0]}}, \"118\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\tdetailed fur\\t\"}}, \"117\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"118\", 0]}}, \"113\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"114\", 0], \"on_false\": [\"117\", 0]}}, \"112\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"113\", 0]}}, \"119\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"110\", 0], \"negative\": [\"112\", 0], \"latent_image\": [\"5\", 0]}}, \"120\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"121\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"122\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"121\", 0]}}, \"123\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"121\", 0]}}, \"124\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"119\", 0]}}, \"125\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"124\", 0]}}, \"126\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"120\", 0]}}, \"130\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\ncafé\", \"inputcount\": 1, \"delimiter\": \",\", \"return_list\": false}}, \"129\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": [\"130\", 0]}}, \"128\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"129\", 0], \"text_l\": \"\"}}, \"132\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"…猫…\", \"prepend_text\": \"\\n😀…\", \"append_text\": \"\\u001cfox…\", \"clip\": [\"4\", 1]}}, \"131\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"132\", 0], \"conditioning_2\": [\"132\", 0]}}, \"127\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"126\", 0], \"model\": [\"4\", 0], \"positive\": [\"128\", 0], \"negative\": [\"131\", 0]}}, \"133\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"127\", 0]}}, \"134\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"127\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt uses a node the inspector does not support (FancyEncoder).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": " café\n"}}, "resolution": {"node": {"class_type": "FancyEncoder", "id": "104"}, "reason": "Unsupported node semantics or output slot", "reason_code": "unsupported-node", "sampler_id": "105", "state": "unresolved"}}, "name": "select-fuzz-0-12", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" café\\n\", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \" detailed fur\"}}, \"103\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"103\", 0], \"conditioning_2\": [\"103\", 0]}}, \"105\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"107\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"106\", 0]}}, \"108\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"106\", 0]}}, \"109\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"106\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-13", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\t猫\", \"text_l\": \"\"}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"104\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \" fox\"}}, \"103\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \"…😀\\t\", \"negative_text\": \"
 a,\\t\"}}, \"105\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"109\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"😀\", \"negative_text\": \" detailed fur…\", \"prepend_text\": \"😀😀\", \"append_text\": \"\\na, \"}}, \"108\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"107\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"109\", 1]}}, \"110\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"108\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"106\", 0]}}, \"112\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"111\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-14", "records": {"parameters": "Negative prompt:\r\ncafé…\r\n"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "café "}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "detailed fur 😀, snow \u001c café
 café"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "105", "state": "resolved"}}, "name": "select-fuzz-0-15", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\u001c\", \"prepend_text\": \"\\nsnow\\u2028 \", \"append_text\": \"\\u001ccaf\\u00e9\\u2028 caf\\u00e9\"}}, \"102\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": [\"103\", 0], \"clean_whitespace\": true}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \" detailed fur\\u3000\\ud83d\\ude00\", \"negative_text\": \"detailed fur\\u001c\"}}, \"104\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u0085\\u732b\\u3000\", \"negative_text\": \"caf\\u00e9\\u3000\", \"prepend_text\": \"detailed fur\\n\", \"append_text\": \"\\u0085caf\\u00e9\\n\"}}, \"105\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 1], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"107\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"106\", 0]}}, \"108\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"106\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "135", "state": "unresolved"}}, "name": "select-fuzz-0-16", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"107\": {\"records\": [{\"text\": \"\\tcaf\\u00e9\\t\", \"negative_text\": \"fox\\u2028 \", \"prepend_text\": \"caf\\u00e9\", \"append_text\": \"snow\\u2028 \\ud83d\\ude00\", \"positive_text\": \"\\u001ca,\\u001c\", \"negative_effective_text\": \"fox\\u2028 \"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u3000detailed fur\\u3000\", \"strip_newlines\": false}}, \"105\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\u0085caf\\u00e9\\u001c\", \"prepend_text\": \"detailed fur\\ufeff\", \"append_text\": \"\\tfox \"}}, \"103\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\u0085a, \", \"string_2\": [\"104\", 0], \"string_3\": [\"105\", 0], \"inputcount\": 3, \"delimiter\": \",\", \"return_list\": false}}, \"102\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": [\"103\", 0], \"text_b\": \" \", \"clean_whitespace\": \"true\"}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\u0085detailed fur\\t\", \"negative_text\": \"\\u001cdetailed fur\\t\"}}, \"107\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\tcaf\\u00e9\\t\", \"negative_text\": \"fox\\u2028 \", \"prepend_text\": \"\\u3000caf\\u00e9\\u0085\", \"append_text\": \" snow\\u2028 \\ud83d\\ude00\"}}, \"106\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"107\", 0], \"conditioning_2\": [\"107\", 0]}}, \"108\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"108\", 0]}}, \"111\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \"\\u2028 a,\", \"text_c\": \"\\u3000a,\\ufeff\", \"clean_whitespace\": \"false\"}}, \"112\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"caf\\u00e9\\t\\u732b\", \"string_b\": \"\\ud83d\\ude00\\u3000\", \"delimiter\": \" \"}}, \"110\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \"\\ufeff\\u732b\\ufeff\", \"text_b\": [\"111\", 0], \"text_d\": [\"112\", 0], \"clean_whitespace\": true}}, \"109\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"110\", 0], \"clip\": [\"4\", 1]}}, \"113\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\ufeffa,\\u001c\", \"text_l\": \"\\ufeffa,\\u001c\"}}, \"114\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"109\", 0], \"negative\": [\"113\", 0], \"latent_image\": [\"5\", 0]}}, \"115\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"108\", 0]}}, \"119\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u0085snow fox\", \"prepend_text\": \"\\tdetailed fur\", \"append_text\": \"\\u2028 \\ufefffox\", \"clip\": [\"4\", 1]}}, \"118\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"119\", 0]}}, \"120\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\u2028 snow \", \"prepend_text\": \" \\ud83d\\ude00\", \"append_text\": \"fox\\u3000\", \"clip\": [\"4\", 1]}}, \"117\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"118\", 0], \"conditioning_2\": [\"120\", 0]}}, \"124\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\na,\", \"clip\": [\"4\", 1]}}, \"123\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"124\", 0]}}, \"122\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"123\", 0]}}, \"121\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"122\", 0]}}, \"116\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"115\", 0], \"model\": [\"4\", 0], \"positive\": [\"117\", 0], \"negative\": [\"121\", 0]}}, \"125\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"116\", 0]}}, \"126\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"114\", 0]}}, \"131\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u3000\\u0085\", \"clip\": [\"4\", 1]}}, \"130\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"131\", 0]}}, \"133\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u3000fox\\t\", \"clip\": [\"4\", 1]}}, \"132\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"133\", 0]}}, \"129\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"130\", 0], \"on_false\": [\"132\", 0]}}, \"128\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"129\", 0]}}, \"134\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\tcaf\\u00e9a,\"}}, \"127\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"126\", 0], \"model\": [\"4\", 0], \"positive\": [\"128\", 0], \"negative\": [\"134\", 0]}}, \"139\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\tdetailed fur\", \"clip\": [\"4\", 1]}}, \"138\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"139\", 0]}}, \"137\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"138\", 0]}}, \"136\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"137\", 0]}}, \"135\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"127\", 0], \"model\": [\"4\", 0], \"positive\": [\"109\", 0], \"negative\": [\"136\", 0]}}, \"140\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"135\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-17", "records": {"parameters": " detailed fur \r\nNegative Template: n\r\nNegative Template: n
Steps:٣, a\r\nNegative prompt: blur
"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Selector branches have different prompts", "reason_code": null, "sampler_id": "110", "state": "ambiguous"}}, "name": "select-fuzz-0-18", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\u0085detailed fur \", \"prepend_text\": \"caf\\u00e9\\u3000detailed fur\", \"negative_text\": \"\\u3000detailed fur \"}}, \"105\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u001csnow\\u0085\", \"prepend_text\": \"\\u0085\\u2028 \", \"append_text\": \"\\n\\ud83d\\ude00\\t\", \"clip\": [\"4\", 1]}}, \"107\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u3000fox\\u001c\", \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"detailed fur\\u001c\", \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"107\", 0], \"on_false\": [\"108\", 0]}}, \"104\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"105\", 0], \"on_false\": [\"106\", 0]}}, \"103\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"109\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"110\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"114\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \" detailed fur\\u2028 \", \"prepend_text\": \"\\tcaf\\u00e9\\t\\u732b\", \"append_text\": \"caf\\u00e9\\ufeff\", \"clip\": [\"4\", 1]}}, \"113\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"114\", 0]}}, \"118\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\u2028 a,\\u2028 \"}}, \"117\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"118\", 0]}}, \"116\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"117\", 0], \"prepend_text\": \"\\u3000\\ud83d\\ude00\\n\", \"append_text\": \"\\u3000a,\\u3000\", \"clip\": [\"4\", 1]}}, \"119\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u3000detailed fur \", \"negative_text\": \"\\tcaf\\u00e9\", \"prepend_text\": \"\\u2028 snow\\n\", \"append_text\": \"\\u2028 snow\\u001c\"}}, \"115\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"116\", 0], \"on_false\": [\"119\", 1]}}, \"112\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"111\", 0], \"model\": [\"4\", 0], \"positive\": [\"113\", 0], \"negative\": [\"115\", 0]}}, \"122\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\ufeffa,\\u001c\", \"prepend_text\": \"\\ncaf\\u00e9\\u2028 \", \"append_text\": \" caf\\u00e9\"}}, \"121\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"122\", 0], \"text_l\": \"\\u2028 detailed fur\\n\"}}, \"120\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"112\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"121\", 0], \"wildcard\": \"\"}}, \"123\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"120\", 0]}}, \"124\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"125\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"124\", 0]}}, \"126\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"124\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-19", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": \"\\t \", \"clean_whitespace\": \"false\"}}, \"102\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\u2028 \\u2028 \", \"string_b\": [\"103\", 0], \"delimiter\": \", \"}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\nsnow\\u001csnow\", \"prepend_text\": \"\\tfox\\t\", \"append_text\": \"\\nfox\", \"clip\": [\"4\", 1]}}, \"105\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\u001c\\ud83d\\ude00\\na,\"}}, \"107\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"108\", 0]}}, \"106\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"107\", 0], \"prepend_text\": \"\\u2028 a, detailed fur\", \"negative_text\": \"\\na,\\u3000\"}}, \"111\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\tsnow\\u3000\", \"prepend_text\": \"\\ufeff\\u732b\\u0085\", \"negative_text\": \"\\u0085detailed fur\\u001c\"}}, \"110\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"111\", 0]}}, \"109\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"110\", 0], \"conditioning_2\": [\"110\", 0]}}, \"112\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"106\", 0], \"negative\": [\"109\", 0], \"latent_image\": [\"5\", 0]}}, \"113\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\ta,\\n\", \"prepend_text\": \"\\u0085\\ndetailed fur\", \"negative_text\": \"\\u3000\\u2028 \"}}, \"114\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"113\", 0], \"latent_image\": [\"5\", 0]}}, \"115\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"119\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\ufeffa,\\u3000\", \"text_l\": \"\\ufeffa,\\u3000\"}}, \"120\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"detailed fur a,\", \"prepend_text\": \"\\tsnow\\t\", \"append_text\": \"\\u0085fox\\n\", \"clip\": [\"4\", 1]}}, \"118\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"119\", 0], \"on_false\": [\"120\", 0]}}, \"117\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"118\", 0]}}, \"121\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\nsnow\\ufefffox\", \"prepend_text\": \"\\u2028 detailed fur \", \"append_text\": \"\\n\\u732b\\u3000\", \"clip\": [\"4\", 1]}}, \"116\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"115\", 0], \"model\": [\"4\", 0], \"positive\": [\"117\", 0], \"negative\": [\"121\", 0]}}, \"126\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\u0085\\t\"}}, \"125\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"126\", 0]}}, \"124\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": [\"125\", 0], \"inputcount\": 1, \"delimiter\": \" \", \"return_list\": false}}, \"123\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"124\", 0], \"clip\": [\"4\", 1]}}, \"127\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\tcaf\\u00e9\\u3000a,\", \"text_l\": \"\\tcaf\\u00e9\\u3000a,\"}}, \"122\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"116\", 0], \"model\": [\"4\", 0], \"positive\": [\"123\", 0], \"negative\": [\"127\", 0]}}, \"128\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"122\", 0]}}, \"129\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"112\", 0]}}, \"130\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"129\", 0]}}, \"131\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"129\", 0]}}, \"132\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"129\", 0]}}, \"133\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"114\", 0]}}, \"137\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\ufeff\\u732b\\u0085\", \"strip_newlines\": false}}, \"136\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"137\", 0]}}, \"135\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"136\", 0], \"prepend_text\": \"\", \"append_text\": \"\\ufeff\\u732b\\u3000\", \"clip\": [\"4\", 1]}}, \"140\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\u0085\\t\", \"prepend_text\": \"\\u2028 snow\\nsnow\", \"negative_text\": \"caf\\u00e9\\u0085caf\\u00e9\"}}, \"139\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"140\", 0]}}, \"138\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"139\", 0]}}, \"134\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"135\", 0], \"negative\": [\"138\", 0], \"upscaled_image\": [\"133\", 0]}}, \"141\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"134\", 0]}}, \"142\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"134\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Sampler stages have different prompts", "reason_code": "multistage-differs", "sampler_id": "111", "state": "ambiguous"}}, "name": "select-fuzz-0-20", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"103\": {\"records\": [{\"text\": \"\\t\\n\", \"negative_text\": \"\\u732b\\ufeff\", \"prepend_text\": \"\\u732bcaf\\u00e9\", \"append_text\": \"\", \"positive_text\": \"\\u2028 detailed fur\\u001c\", \"negative_effective_text\": \"\\u732b\\ufeff\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\t\\n\", \"negative_text\": \"猫\", \"prepend_text\": \"…猫café\", \"append_text\": \"\\n\\n\"}}, \"104\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\ta,
 \"}}, \"102\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"103\", 1], \"on_false\": [\"104\", 0]}}, \"105\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"… snow\", \"prepend_text\": \"\\tdetailed fur\", \"negative_text\": \"\\na,猫\"}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"102\", 0], \"on_false\": [\"105\", 0]}}, \"108\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"
 snow \", \"prepend_text\": \"fox\\n\", \"append_text\": \"…😀 \"}}, \"107\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"108\", 0]}}, \"106\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"107\", 0], \"prepend_text\": \"\\nfox
 \", \"append_text\": \"😀 \", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"110\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"115\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" fox\\t\", \"clip\": [\"4\", 1]}}, \"116\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"snow
 \", \"clip\": [\"4\", 1]}}, \"114\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_2\": [\"116\", 0]}}, \"113\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"114\", 0]}}, \"112\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"113\", 0]}}, \"111\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"110\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"112\", 0]}}, \"117\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"111\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Cyclic latent ancestry", "reason_code": "malformed", "sampler_id": "108", "state": "unresolved"}}, "name": "select-fuzz-0-21", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u001c\\ud83d\\ude00\\u3000\\ud83d\\ude00\", \"strip_newlines\": false}}, \"101\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"102\", 0], \"text_l\": \"\"}}, \"106\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u0085snow\\u2028 \", \"strip_newlines\": true}}, \"107\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u3000\\u732b\\ufeff\", \"strip_newlines\": false}}, \"105\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": [\"106\", 0], \"text_c\": [\"107\", 0], \"clean_whitespace\": true}}, \"104\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \" detailed fur snow\", \"string_2\": [\"105\", 0], \"inputcount\": 3, \"delimiter\": \",\", \"return_list\": false}}, \"103\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \"\\u2028 \\u732b\\n\", \"negative_text\": \"\\u0085caf\\u00e9\\u001c\"}}, \"108\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"108\", 0]}}, \"109\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"108\", 0]}}, \"110\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"109\", 0]}}, \"111\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"109\", 0]}}, \"112\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"109\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-22", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"110\": {\"records\": [{\"text\": \"\\n\\u3000snow\", \"negative_text\": \"\\u001csnow\\t\", \"prepend_text\": \"\\ufefffox\", \"append_text\": \"\\u732b\\ufeffdetailed fur\", \"positive_text\": \"caf\\u00e9\\u2028 \", \"negative_effective_text\": \"\\u001csnow\\t\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ufeffsnow\\u3000\", \"negative_text\": \"\\u3000snow \", \"prepend_text\": \"\\ufeffa,\\tdetailed fur\", \"append_text\": \"\\u001cfox\"}}, \"101\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"102\", 1]}}, \"103\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\u0085\\ud83d\\ude00\"}}, \"104\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": \"\\u001ca,\\u2028 \"}}, \"107\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"108\", 0], \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"107\", 0]}}, \"105\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"106\", 0], \"conditioning_2\": [\"106\", 0]}}, \"110\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\n\\u3000snow\", \"negative_text\": \"\\u001csnow\\t\", \"prepend_text\": \"\\ufefffox\\u0085\", \"append_text\": \" \\u732b\\ufeffdetailed fur\"}}, \"114\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t\\ud83d\\ude00\\u2028 \\u732b\", \"clip\": [\"4\", 1]}}, \"113\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"114\", 0]}}, \"115\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\ncaf\\u00e9\\t\", \"prepend_text\": \"\\u2028 \\ud83d\\ude00\", \"append_text\": \"\\nfox\\u3000detailed fur\", \"clip\": [\"4\", 1]}}, \"112\": {\"class_type\": \"ConditioningCombine\"}, \"111\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"112\", 0]}}, \"109\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"110\", 0], \"on_false\": [\"111\", 0]}}, \"116\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"105\", 0], \"negative\": [\"109\", 0], \"latent_image\": [\"5\", 0]}}, \"117\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"105\", 0], \"negative\": [\"109\", 0], \"latent_image\": [\"5\", 0]}}, \"118\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"119\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"118\", 0]}}, \"120\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"116\", 0]}}, \"124\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\u001cdetailed fur\\u0085\", \"prepend_text\": \"\\u001csnow\\t\", \"append_text\": \"\\nfox\"}}, \"123\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"124\", 0], \"strip_newlines\": true}}, \"122\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"123\", 0], \"clip\": [\"4\", 1]}}, \"121\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"120\", 0], \"model\": [\"4\", 0], \"positive\": [\"105\", 0], \"negative\": [\"122\", 0]}}, \"127\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"caf\\u00e9\\u0085\"}}, \"126\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"127\", 0]}}, \"125\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"121\", 0], \"model\": [\"4\", 0], \"positive\": [\"105\", 0], \"negative\": [\"126\", 0]}}, \"128\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"125\", 0]}}, \"129\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"117\", 0]}}, \"133\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\ufeff\\ud83d\\ude00\\ufeff\\ud83d\\ude00\", \"prepend_text\": \"\\u0085a,\\u3000\", \"append_text\": \"\\u3000\\ud83d\\ude00\\n\\u732b\", \"clip\": [\"4\", 1]}}, \"132\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"133\", 0]}}, \"131\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"132\", 0]}}, \"134\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u2028 caf\\u00e9\\u2028 \", \"negative_text\": \"\\u2028 \\u0085\\ud83d\\ude00\", \"prepend_text\": \"\\ufefffox\\n\", \"append_text\": \"\\ufeffsnowsnow\"}}, \"130\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"129\", 0], \"model\": [\"4\", 0], \"positive\": [\"131\", 0], \"negative\": [\"134\", 0]}}, \"135\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"130\", 0]}}, \"136\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"130\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "execution", "status": "resolved", "text": "😀\t"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "fox snowfox \u001csnow snow snow \tsnow  fox 😀"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "118", "state": "resolved"}}, "name": "select-fuzz-0-23", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"117\": {\"records\": [{\"text\": \"\\ufeffcaf\\u00e9\\u2028 \", \"negative_text\": \"\\t\\u732b\\t\", \"prepend_text\": \"\\ufeff\\ud83d\\ude00\\u001cdetailed fur\", \"append_text\": \"fox\", \"positive_text\": \"\\ud83d\\ude00\\t\", \"negative_effective_text\": \"\\t\\u732b\\t\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\u0085snow\\u3000\"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"106\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": \"\\u0085\\u732b\\u3000caf\\u00e9\", \"clean_whitespace\": \"true\"}}, \"103\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": [\"104\", 0], \"text_d\": [\"106\", 0], \"clean_whitespace\": \"false\"}}, \"102\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\nfox\", \"negative_text\": \"caf\\u00e9\\u2028 \\ud83d\\ude00\", \"prepend_text\": \"\\u0085\\u732b\", \"append_text\": \"\\ta,\\u001c\"}}, \"108\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"109\", 1]}}, \"107\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"108\", 0]}}, \"110\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"111\", 0]}}, \"111\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"115\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\u001csnow\\u3000snow\", \"prepend_text\": \"\\u0085snowfox\", \"append_text\": \"\\tsnow\\u3000\"}}, \"116\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\tsnow\\u3000\"}}, \"114\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"115\", 0], \"string_b\": [\"116\", 0], \"delimiter\": \" \"}}, \"113\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": [\"114\", 0]}}, \"112\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"113\", 0], \"prepend_text\": \"\\nfox\\n\", \"append_text\": \"fox\\u3000\\ud83d\\ude00\", \"clip\": [\"4\", 1]}}, \"117\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\ufeffcaf\\u00e9\\u2028 \", \"negative_text\": \"\\t\\u732b\\t\", \"prepend_text\": \"\\ufeff\\ud83d\\ude00\\u001cdetailed fur\", \"append_text\": \"fox\\u2028 \"}}, \"118\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"112\", 0], \"negative\": [\"117\", 0], \"latent_image\": [\"5\", 0]}}, \"119\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"120\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"119\", 0]}}, \"121\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"111\", 0]}}, \"122\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"121\", 0]}}, \"123\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"118\", 0]}}, \"124\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"123\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (PromptSearchList).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "PromptSearchList", "id": "114"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "121", "state": "unresolved"}}, "name": "select-fuzz-0-24", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"101\": {\"records\": [{\"text\": \" a,\\ufeff\", \"negative_text\": \"\\u3000\\u2028 \", \"prepend_text\": \"\\u732b\", \"append_text\": \"a,\", \"positive_text\": \"detailed fur \", \"negative_effective_text\": \"\\u3000\\u2028 \"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" a,\\ufeff\", \"negative_text\": \"\\u3000\\u2028 \", \"prepend_text\": \" \\u732b\\t\", \"append_text\": \"\\u2028 a,\\t\"}}, \"105\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u2028 fox\\u3000\", \"strip_newlines\": false}}, \"104\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": [\"105\", 0], \"prepend_text\": \"\\u0085fox\\n\", \"append_text\": \"\\ufeffsnow\\u0085\"}}, \"103\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \"\\nfox\\u2028 \", \"append_text\": \"a,\", \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\u3000fox\\n\", \"prepend_text\": \"\\ufeffa,\\t\", \"negative_text\": \"\\ufeffcaf\\u00e9\\u3000\"}}, \"109\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\nfox\\ufeff\"}}, \"107\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"108\", 0], \"on_false\": [\"109\", 0]}}, \"106\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"107\", 0]}}, \"102\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"103\", 0], \"on_false\": [\"106\", 0]}}, \"110\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"114\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u2028 detailed fur\\u3000detailed fur\"}}, \"113\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"114\", 0]}}, \"117\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\n\\ud83d\\ude00\\n\", \"clip\": [\"4\", 1]}}, \"116\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"117\", 0]}}, \"119\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\na,\\t\", \"clip\": [\"4\", 1]}}, \"120\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t\\ud83d\\ude00\\u2028 snow\", \"clip\": [\"4\", 1]}}, \"118\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"119\", 0], \"on_false\": [\"120\", 0]}}, \"115\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"116\", 0], \"conditioning_2\": [\"118\", 0]}}, \"112\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"113\", 0], \"on_false\": [\"115\", 0]}}, \"111\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"112\", 0]}}, \"121\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"111\", 0], \"latent_image\": [\"5\", 0]}}, \"125\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\u2028 \\n\\ud83d\\ude00\", \"text_l\": \"\\u2028 \\n\\ud83d\\ude00\"}}, \"127\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u0085fox\\u732b\", \"clip\": [\"4\", 1]}}, \"128\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t \\ud83d\\ude00\", \"clip\": [\"4\", 1]}}, \"126\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"127\", 0], \"on_false\": [\"128\", 0]}}, \"124\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"125\", 0], \"on_false\": [\"126\", 0]}}, \"123\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"124\", 0]}}, \"122\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"123\", 0]}}, \"132\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\u001cdetailed fur\\ufeff\", \"string_3\": \" snow\\u2028 \", \"inputcount\": 4, \"delimiter\": \",\", \"return_list\": false}}, \"131\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"132\", 0]}}, \"130\": {\"class_type\": \"StringConstant\", \"inputs\": {\"string\": [\"131\", 0]}}, \"129\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"130\", 0], \"prepend_text\": \" \\u732bsnow\", \"append_text\": \"\\u001csnow\\u3000\", \"clip\": [\"4\", 1]}}, \"133\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"122\", 0], \"negative\": [\"129\", 0], \"latent_image\": [\"5\", 0]}}, \"134\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"139\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001c\\u001c\\ud83d\\ude00\", \"clip\": [\"4\", 1]}}, \"138\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"139\", 0]}}, \"137\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"138\", 0]}}, \"136\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"137\", 0]}}, \"135\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"134\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"136\", 0], \"wildcard\": [\"4\", 0]}}, \"140\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"135\", 0]}}, \"141\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"121\", 0]}}, \"142\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"141\", 0]}}, \"143\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"133\", 0]}}, \"144\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"143\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "CLIPTextEncodeSDXL", "id": "102"}, "reason": "Encoder parts have different texts", "reason_code": "composite", "sampler_id": "112", "state": "unresolved"}}, "name": "select-fuzz-0-25", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"109\": {\"records\": [{\"text\": \" caf\\u00e9\\u3000snow\", \"negative_text\": \"\\u2028 caf\\u00e9\\ufeff\\ud83d\\ude00\", \"prepend_text\": \"\\u732b\", \"append_text\": \"\", \"positive_text\": \"\\u3000detailed fur\\u2028 caf\\u00e9\", \"negative_effective_text\": \"\\u2028 caf\\u00e9\\ufeff\\ud83d\\ude00\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"105\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\ncafé\"}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"103\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\t猫\", \"string_2\": [\"104\", 0], \"inputcount\": 2, \"delimiter\": \",\", \"return_list\": false}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"103\", 0], \"text_l\": \"\\u001c猫 \"}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"102\", 0]}}, \"109\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" café snow\", \"negative_text\": \"
 café😀\", \"prepend_text\": \"
 猫\\t\", \"append_text\": \"\\u001c…\"}}, \"108\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"109\", 1], \"conditioning_2\": [\"109\", 1]}}, \"107\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"108\", 0]}}, \"106\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"107\", 0], \"conditioning_2\": [\"107\", 0]}}, \"110\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"113\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" \\t猫\", \"negative_text\": \"\\nsnow \", \"prepend_text\": \"
 猫
 \", \"append_text\": \" 猫 \"}}, \"112\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"111\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"113\", 1]}}, \"114\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"112\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-26", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"112\": {\"records\": [{\"text\": \"\\ufeffa,\\t\", \"negative_text\": \"\\u3000\\ud83d\\ude00\\ncaf\\u00e9\", \"prepend_text\": \"\", \"append_text\": \"fox\", \"positive_text\": \"\\u0085snow \", \"negative_effective_text\": \"\\u3000\\ud83d\\ude00\\ncaf\\u00e9\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\n\\n\"}}, \"102\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" \", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"105\", 0]}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"102\", 0], \"on_false\": [\"104\", 0]}}, \"109\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"…snow\\n\", \"prepend_text\": \" 猫\", \"append_text\": \"\\ta,\\ta,\"}}, \"108\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": [\"109\", 0], \"inputcount\": 1, \"delimiter\": \",\", \"return_list\": false}}, \"107\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"108\", 0], \"prepend_text\": \" a,\\n😀\", \"append_text\": \"
 detailed fur \", \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"107\", 0], \"conditioning_2\": [\"107\", 0]}}, \"110\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"112\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"a,\\t\", \"negative_text\": \" 😀\\ncafé\", \"prepend_text\": \"\\t
 \", \"append_text\": \"\\tfox\\u001c\"}}, \"111\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"112\", 0]}}, \"113\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"😀\\u001c\"}}, \"114\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"111\", 0], \"negative\": [\"113\", 0], \"latent_image\": [\"5\", 0]}}, \"115\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"116\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"115\", 0]}}, \"117\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"114\", 0]}}, \"119\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"猫\\t\"}}, \"120\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\tsnow 😀\"}}, \"118\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"117\", 0], \"model\": [\"4\", 0], \"positive\": [\"119\", 0], \"negative\": [\"120\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-27", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"127\": {\"records\": [{\"text\": \"\\u2028 \\ud83d\\ude00 \\ud83d\\ude00\", \"negative_text\": \"\\u732b \", \"prepend_text\": \"\\ufeffcaf\\u00e9\", \"append_text\": \"\", \"positive_text\": \" snow\\u001cdetailed fur\", \"negative_effective_text\": \"\\u732b \"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\u001cdetailed fur \", \"prepend_text\": \"\\u001c猫\\n\", \"negative_text\": \"\\t猫
 a,\"}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"103\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"104\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"…detailed fur\\n\", \"negative_text\": \"\\u001c猫\\u001c\", \"prepend_text\": \"\\u001csnow…fox\", \"append_text\": \" \"}}, \"106\": {\"class_type\": \"StringConstantMultiline\"}, \"105\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"106\", 0], \"prepend_text\": \"\\ndetailed fur\", \"append_text\": \"\\t\\u001c\", \"clip\": [\"4\", 1]}}, \"107\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"104\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"112\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"…detailed fur\\t\", \"strip_newlines\": true}}, \"111\": {\"class_type\": \"TextInput\", \"inputs\": {\"text\": [\"112\", 0]}}, \"110\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"111\", 0], \"text_l\": [\"111\", 0]}}, \"115\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \" detailed fur…\"}}, \"114\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"115\", 0]}}, \"113\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"114\", 0], \"prepend_text\": \" \\tdetailed fur\", \"negative_text\": \"猫 \"}}, \"109\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"110\", 0], \"negative\": [\"113\", 0], \"upscaled_image\": [\"108\", 0]}}, \"120\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001c😀
 a,\", \"clip\": [\"4\", 1]}}, \"119\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"120\", 0]}}, \"118\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"119\", 0]}}, \"117\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"118\", 0], \"conditioning_2\": [\"118\", 0]}}, \"121\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"…\\n\", \"clip\": [\"4\", 1]}}, \"116\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"109\", 0], \"model\": [\"4\", 0], \"positive\": [\"117\", 0], \"negative\": [\"121\", 0]}}, \"122\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"116\", 0]}}, \"123\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"127\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"
 😀 😀\", \"negative_text\": \"猫 \", \"prepend_text\": \"café\\t\", \"append_text\": \"\\t\"}}, \"129\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a,\\t\", \"clip\": [\"4\", 1]}}, \"128\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"129\", 0]}}, \"126\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"127\", 0], \"conditioning_2\": [\"128\", 0]}}, \"131\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u001ca,
 \", \"strip_newlines\": false}}, \"130\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"131\", 0], \"clip\": [\"4\", 1]}}, \"125\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"126\", 0], \"on_false\": [\"130\", 0]}}, \"135\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\n…\", \"clip\": [\"4\", 1]}}, \"134\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"135\", 0]}}, \"133\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"134\", 0]}}, \"138\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001c猫\", \"clip\": [\"4\", 1]}}, \"137\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"138\", 0]}}, \"139\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\ndetailed fur…\", \"prepend_text\": \" \", \"negative_text\": \"a,猫\"}}, \"136\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"137\", 0], \"on_false\": [\"139\", 0]}}, \"132\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"133\", 0], \"on_false\": [\"136\", 0]}}, \"124\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"123\", 0], \"model\": [\"4\", 0], \"positive\": [\"125\", 0], \"negative\": [\"132\", 0]}}, \"140\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"124\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-28", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"101\": {\"records\": [{\"text\": \"\\u001c\\u732b \", \"negative_text\": \"\\u2028 \\u0085\", \"prepend_text\": \"\\u732b\", \"append_text\": \"\", \"positive_text\": \"snow\\u0085\", \"negative_effective_text\": \"\\u2028 \\u0085\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001c\\u732b \", \"negative_text\": \"\\u2028 \\u0085\", \"prepend_text\": \"\\u732b\\u001c\", \"append_text\": \"\\u3000\\u2028 \"}}, \"102\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u001c\\u3000\"}}, \"103\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"104\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"105\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"107\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"110\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u0085fox\\u3000\"}}, \"109\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"110\", 0]}}, \"114\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"\\ndetailed fur\"}}, \"113\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"114\", 0]}}, \"112\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"113\", 0], \"text_l\": [\"113\", 0]}}, \"116\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \"detailed fur\\u3000detailed fur\", \"text_d\": \"\\ufeff\\ud83d\\ude00\\u2028 \", \"text_c\": \"\\tsnow \", \"clean_whitespace\": true}}, \"115\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"116\", 0], \"prepend_text\": \"\\u001c\\ud83d\\ude00\\u001c\", \"negative_text\": \"\\u001ca,\\ufeff\\ud83d\\ude00\"}}, \"111\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"112\", 0], \"conditioning_2\": [\"115\", 0]}}, \"108\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"109\", 0], \"negative\": [\"111\", 0], \"upscaled_image\": [\"107\", 0]}}, \"118\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u3000snow\\u3000snow\", \"negative_text\": \"\\u0085fox\\u001c\", \"prepend_text\": \"foxcaf\\u00e9\", \"append_text\": \"\\ufeffsnow\\tcaf\\u00e9\"}}, \"117\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"108\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"118\", 0]}}, \"119\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"117\", 0]}}, \"120\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"122\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\ufeffcaf\\u00e9\\u2028 a,\", \"prepend_text\": \"\\u3000caf\\u00e9 \", \"append_text\": \"\\u732b \", \"clip\": [\"4\", 1]}}, \"121\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"101\", 1], \"negative\": [\"122\", 0], \"upscaled_image\": [\"120\", 0]}}, \"123\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"121\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-29", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\u3000a,\\u001c\", \"text_l\": \"\\u3000a,\\u001c\"}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"103\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\ncaf\\u00e9\\t\", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"105\", 0]}}, \"105\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u0085a,\\n\", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \" \\u732b\\u0085\"}}, \"108\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"109\", 0]}}, \"107\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"108\", 0], \"prepend_text\": \" \\ud83d\\ude00\\u3000\", \"negative_text\": \"a,\\n\"}}, \"110\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"106\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"104\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"115\": {\"class_type\": \"StringConstant\", \"inputs\": {\"text\": \"\\ncaf\\u00e9\\u001c\"}}, \"114\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": [\"115\", 0], \"inputcount\": 1, \"delimiter\": \" \", \"return_list\": false}}, \"113\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"114\", 0], \"clip\": [\"4\", 1]}}, \"112\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"111\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"113\", 0]}}, \"116\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"117\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"116\", 0]}}, \"121\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\u732b\\ufeff\", \"strip_newlines\": false}}, \"120\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"121\", 0], \"prepend_text\": \"\\u0085a,\\u0085fox\", \"append_text\": \"\\u3000a,\\t\", \"clip\": [\"4\", 1]}}, \"123\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\u732b\\ufeff\"}}, \"122\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"123\", 0]}}, \"119\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"120\", 0], \"on_false\": [\"122\", 0]}}, \"118\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"116\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"119\", 0]}}, \"124\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"118\", 0]}}, \"125\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"126\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"125\", 0]}}, \"127\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"125\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt is chosen at run time (JoinStringMulti).", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt is chosen at run time (JoinStringMulti).", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": {"class_type": "JoinStringMulti", "id": "104"}, "reason": "Text is decided at run time", "reason_code": "runtime-value", "sampler_id": "107", "state": "unresolved"}}, "name": "select-fuzz-0-30", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\u001c😀\\u001c\", \"string_2\": \"猫 detailed fur\", \"string_3\": \"detailed fur
 😀\", \"inputcount\": 3, \"delimiter\": \" \", \"return_list\": true}}, \"103\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"
 detailed fur…\", \"string_2\": [\"104\", 0], \"inputcount\": 2, \"delimiter\": \",\", \"return_list\": false}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"103\", 0], \"text_l\": [\"103\", 0]}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"106\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \" snow\\n\"}}, \"105\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"106\", 0], \"prepend_text\": \"\\t…\", \"negative_text\": \"\\t\\u001c\"}}, \"107\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"109\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"108\", 0]}}, \"110\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"108\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-31", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"102\": {\"records\": [{\"text\": \"\\tsnow\\u0085fox\", \"negative_text\": \"\\ufeff \", \"prepend_text\": \"caf\\u00e9\\ufeff\", \"append_text\": \"snow\", \"positive_text\": \"\\ufeffa,\", \"negative_effective_text\": \"\\ufeff \"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\tsnow…fox\", \"negative_text\": \" \", \"prepend_text\": \"café\", \"append_text\": \"\\u001csnow\\u001c\"}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"103\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\u001ca,\\t\", \"text_l\": \"\"}}, \"104\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"104\", 0]}}, \"107\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\t…\", \"strip_newlines\": false}}, \"106\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": [\"107\", 0], \"text_d\": \"\\t\\t\", \"clean_whitespace\": \"true\"}}, \"105\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"106\", 0], \"prepend_text\": \"café \", \"append_text\": \"a,\\ta,\", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"…😀…\", \"text_l\": \"\\n😀\\tcafé\"}}, \"112\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"detailed fur \", \"inputcount\": 1, \"delimiter\": \",\", \"return_list\": false}}, \"111\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"112\", 0], \"text_l\": \"snow\\t\"}}, \"110\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"111\", 0]}}, \"108\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"109\", 0], \"on_false\": [\"110\", 0]}}, \"113\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"105\", 0], \"negative\": [\"108\", 0], \"latent_image\": [\"5\", 0]}}, \"114\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"118\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\tdetailed fur\\u001c\", \"string_2\": \"\\tsnow\\n\", \"inputcount\": 3, \"delimiter\": \",\", \"return_list\": false}}, \"117\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"118\", 0], \"prepend_text\": \"snow…\", \"append_text\": \"\\u001ccafé\", \"clip\": [\"4\", 1]}}, \"116\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"117\", 0], \"conditioning_2\": [\"117\", 0]}}, \"115\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"114\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"116\", 0], \"wildcard\": \"x\"}}, \"119\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"115\", 0]}}, \"120\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"113\", 0]}}, \"121\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"120\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-32", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"102\": {\"records\": [{\"text\": \"\\u001cfox\\tsnow\", \"negative_text\": \"\\u001c\\t\", \"prepend_text\": \"detailed fur\", \"append_text\": \"\\u732b\", \"positive_text\": \"\\tfox\", \"negative_effective_text\": \"\\u001c\\t\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001cfox\\tsnow\", \"negative_text\": \"\\u001c\\t\", \"prepend_text\": \"
 detailed fur \", \"append_text\": \"…猫…\"}}, \"103\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\u001c猫 \", \"text_l\": \"\\ta, \"}}, \"101\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"102\", 1], \"on_false\": [\"103\", 0]}}, \"104\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"fox 猫\", \"clip\": [\"4\", 1]}}, \"107\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"108\", 0]}}, \"106\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"107\", 0]}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}, \"109\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"…😀\\u001c\"}}, \"110\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"105\", 0], \"negative\": [\"109\", 0], \"latent_image\": [\"5\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"112\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"111\", 0]}}, \"113\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"111\", 0]}}, \"114\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"115\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"114\", 0]}}, \"116\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"114\", 0]}}, \"117\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"114\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-33", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"😀 \", \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\t\\n\"}}, \"103\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_d\": \"\\ndetailed fur\\tfox\", \"text_a\": \"
 fox \", \"text_b\": \" café\\t\", \"clean_whitespace\": true}}, \"106\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": [\"107\", 0], \"string_2\": \" \\t\", \"inputcount\": 2, \"delimiter\": \" \", \"return_list\": false}}, \"105\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"106\", 0], \"text_l\": \"\"}}, \"104\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"105\", 0]}}, \"108\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"109\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"110\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"111\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"110\", 0]}}, \"112\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"110\", 0]}}, \"113\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"108\", 0]}}, \"115\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"猫…\", \"text_l\": \"猫…\"}}, \"116\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u001cfox\", \"prepend_text\": \"…a,\\t\", \"append_text\": \"
 😀café\", \"clip\": [\"4\", 1]}}, \"114\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"113\", 0], \"model\": [\"4\", 0], \"positive\": [\"115\", 0], \"negative\": [\"116\", 0]}}, \"117\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"121\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \" café\\u001c\", \"prepend_text\": \"\\ta,\", \"append_text\": \"\\tdetailed furcafé\"}}, \"120\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": [\"121\", 0]}}, \"119\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"120\", 0], \"prepend_text\": \"\\tsnow \", \"append_text\": \"
 
 \", \"clip\": [\"4\", 1]}}, \"118\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"117\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"119\", 0]}}, \"122\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"118\", 0]}}, \"123\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"118\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-34", "records": {"parameters": "Negative prompt: blur"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-35", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"102\": {\"records\": [{\"text\": \"\\u001c\\u3000\", \"negative_text\": \"\\n\", \"prepend_text\": \"a,\", \"append_text\": \"\\ud83d\\ude00\\t\\ud83d\\ude00\", \"positive_text\": \" a,\\u3000\\ud83d\\ude00\", \"negative_effective_text\": \"\\n\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"detailed fur\\u0085\\ud83d\\ude00\"}}, \"102\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001c\\u3000\", \"negative_text\": \"\\n\", \"prepend_text\": \"\\u3000a,\\n\", \"append_text\": \"\\u0085\\ud83d\\ude00\\t\\ud83d\\ude00\"}}, \"103\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"104\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"105\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"106\": {\"class_type\": \"PreviewAny\"}, \"107\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-36", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \"\\u001csnow\\t\", \"text_c\": \"
 fox…\", \"clean_whitespace\": true}}, \"105\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \" a, \", \"inputcount\": 1, \"delimiter\": \",\", \"return_list\": false}}, \"103\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \" fox\", \"text_b\": [\"104\", 0], \"text_c\": [\"105\", 0], \"clean_whitespace\": \"false\"}}, \"102\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"103\", 0], \"text_l\": \"\\u001ccafé…fox\"}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"107\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"café\", \"prepend_text\": \"fox detailed fur\", \"append_text\": \"\\t猫
 fox\", \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"107\", 0]}}, \"108\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 0], \"latent_image\": [\"5\", 0]}}, \"112\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"fox\\n\"}}, \"111\": {\"class_type\": \"StringConstant\", \"inputs\": {\"text\": [\"112\", 0]}}, \"110\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"111\", 0], \"prepend_text\": \"\\t猫\\nsnow\", \"append_text\": \"\\u001ca,…\", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"110\", 0]}}, \"115\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \" snowdetailed fur\", \"prepend_text\": \"\\ndetailed fur \", \"append_text\": \"…fox
 detailed fur\", \"clip\": [\"4\", 1]}}, \"114\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"115\", 0]}}, \"113\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"114\", 0]}}, \"116\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"109\", 0], \"negative\": [\"113\", 0], \"latent_image\": [\"108\", 0]}}, \"117\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"108\", 0]}}, \"118\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"116\", 0]}}, \"120\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\tcafé
 \", \"clip\": [\"4\", 1]}}, \"119\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"118\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"120\", 0]}}, \"121\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"119\", 0]}}, \"122\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"119\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-37", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\na,\\n\\u732b\", \"string_b\": \"\\u3000snow\\u2028 \", \"delimiter\": \" \"}}, \"102\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \" \\ud83d\\ude00\\ufeff\", \"string_2\": [\"103\", 0], \"inputcount\": 2, \"delimiter\": \" \", \"return_list\": false}}, \"101\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\u0085detailed fur\", \"append_text\": \"detailed fur \\u732b\", \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": \" \\ud83d\\ude00\\u001c\\ud83d\\ude00\"}}, \"105\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"106\", 0], \"string_b\": \"\\u2028 \\u732b \", \"delimiter\": \"\"}}, \"104\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"105\", 0], \"text_l\": [\"105\", 0]}}, \"107\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"110\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"detailed fur \", \"prepend_text\": \"\\tsnow \", \"append_text\": \"\\n\\ud83d\\ude00 \"}}, \"109\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_c\": \"\\ufeffdetailed fur\\ufeff\", \"text_d\": [\"110\", 0], \"clean_whitespace\": true}}, \"108\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"109\", 0], \"text_l\": \"\\u001cfox\"}}, \"114\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \" caf\\u00e9\\u001c\"}}, \"113\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"114\", 0]}}, \"112\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"113\", 0]}}, \"111\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"112\", 0]}}, \"115\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"108\", 0], \"negative\": [\"111\", 0], \"latent_image\": [\"5\", 0]}}, \"116\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"117\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"115\", 0]}}, \"121\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \" snow\\ufeff\", \"strip_newlines\": false}}, \"120\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"121\", 0], \"text_l\": [\"121\", 0]}}, \"123\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\nfox\\u3000a,\", \"text_l\": \"\\nfox\\u3000a,\"}}, \"122\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"123\", 0]}}, \"119\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"120\", 0], \"on_false\": [\"122\", 0]}}, \"118\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"117\", 0], \"model\": [\"4\", 0], \"positive\": [\"108\", 0], \"negative\": [\"119\", 0]}}, \"124\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"118\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "execution", "status": "resolved", "text": " a,"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "a,a,"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "105", "state": "resolved"}}, "name": "select-fuzz-0-38", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"104\": {\"records\": [{\"text\": \"\\u3000fox\\u2028 \", \"negative_text\": \" a,\", \"prepend_text\": \"caf\\u00e9\", \"append_text\": \"\\ud83d\\ude00\", \"positive_text\": \" \\u732b\\u3000\", \"negative_effective_text\": \" a,\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": \"a,\\u0085\"}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\u0085a,\\u0085\", \"negative_text\": \"\\u3000\\u732b\"}}, \"104\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u3000fox\\u2028 \", \"negative_text\": \" a,\", \"prepend_text\": \" caf\\u00e9\", \"append_text\": \"\\u2028 \\ud83d\\ude00\\n\"}}, \"105\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 1], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"107\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"106\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "\n猫 fox"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "猫a,caféfox"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "103", "state": "resolved"}}, "name": "select-fuzz-0-39", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"caféfox\", \"prepend_text\": \"\\n猫a,\", \"negative_text\": \"
 a,\"}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\n猫 fox\", \"clip\": [\"4\", 1]}}, \"103\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\t😀
 detailed fur\", \"strip_newlines\": true}}, \"106\": {\"class_type\": \"StringConstant\", \"inputs\": {\"text\": [\"107\", 0]}}, \"105\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"106\", 0], \"prepend_text\": \"猫 😀\", \"append_text\": \" a,\\u001c\", \"clip\": [\"4\", 1]}}, \"104\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"105\", 0]}}, \"108\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\u001ca, \", \"prepend_text\": \"…fox \", \"negative_text\": \"…snow
 fox\"}}, \"109\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"104\", 0], \"negative\": [\"108\", 0], \"latent_image\": [\"5\", 0]}}, \"110\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"104\", 0], \"negative\": [\"108\", 0], \"latent_image\": [\"5\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"112\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"113\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"112\", 0]}}, \"114\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"115\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"114\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Cyclic latent ancestry", "reason_code": "malformed", "sampler_id": "103", "state": "unresolved"}}, "name": "select-fuzz-0-40", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"😀 \", \"prepend_text\": \" café \", \"negative_text\": \"…😀\\n\"}}, \"102\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \" snow\\t\", \"prepend_text\": \"\\u001ca,…\", \"negative_text\": \" a,\\t\"}}, \"103\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"103\", 0]}}, \"104\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"105\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"104\", 0]}}, \"106\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"104\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-41", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"108\": {\"records\": [{\"text\": \"\\u001csnow\\t\\ud83d\\ude00!\", \"negative_text\": \"\\u3000\\ud83d\\ude00 \", \"prepend_text\": \"\\ud83d\\ude00\\u0085\\u732b\", \"append_text\": \"\\ufefffox\", \"positive_text\": \"\\nsnow\\u2028 a,\", \"negative_effective_text\": \"\\u3000\\ud83d\\ude00 \"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"café\\n\", \"prepend_text\": \"\\nsnow\", \"negative_text\": \" fox…fox\"}}, \"103\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"104\", 0], \"conditioning_2\": [\"104\", 0]}}, \"107\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\t \", \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"107\", 0]}}, \"108\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001csnow\\t😀\", \"negative_text\": \" 😀 \", \"prepend_text\": \"…😀…猫\", \"append_text\": \"fox \"}}, \"105\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"106\", 0], \"conditioning_2\": [\"108\", 0]}}, \"102\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"103\", 0], \"on_false\": [\"105\", 0]}}, \"101\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"110\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"😀\\t😀\", \"prepend_text\": \"…😀\\n\", \"negative_text\": \"snow\\t\"}}, \"109\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"110\", 0]}}, \"111\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"109\", 0], \"latent_image\": [\"5\", 0]}}, \"112\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"109\", 0], \"latent_image\": [\"5\", 0]}}, \"116\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\tcafé
 detailed fur\", \"text_l\": \"\\tcafé
 detailed fur\"}}, \"115\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"116\", 0]}}, \"114\": {\"class_type\": null, \"inputs\": {\"value\": [\"115\", 0]}}, \"113\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"114\", 0]}}, \"118\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a,…\", \"clip\": [\"4\", 1]}}, \"117\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"118\", 0]}}, \"119\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"113\", 0], \"negative\": [\"117\", 0], \"latent_image\": [\"5\", 0]}}, \"120\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"111\", 0]}}, \"125\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\ncafé\\t\", \"clip\": [\"4\", 1]}}, \"124\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"125\", 0]}}, \"126\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"…snow\\t\", \"text_l\": \"…snow\\t\"}}, \"123\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"124\", 0], \"conditioning_2\": [\"126\", 0]}}, \"122\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"123\", 0]}}, \"128\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"…café\\u001c\", \"prepend_text\": \"\\ta,\", \"append_text\": \"…a,\\u001c\", \"clip\": [\"4\", 1]}}, \"127\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"128\", 0]}}, \"121\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"122\", 0], \"negative\": [\"127\", 0], \"upscaled_image\": [\"120\", 0]}}, \"129\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"121\", 0]}}, \"130\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"112\", 0]}}, \"131\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"130\", 0]}}, \"132\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"130\", 0]}}, \"133\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"119\", 0]}}, \"135\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" \", \"clip\": [\"4\", 1]}}, \"134\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"133\", 0], \"model\": [\"4\", 0], \"positive\": [\"113\", 0], \"negative\": [\"135\", 0]}}, \"138\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\ndetailed fur\", \"strip_newlines\": false}}, \"137\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"138\", 0], \"prepend_text\": \" detailed fur café\", \"append_text\": \"\\ta, \", \"clip\": [\"4\", 1]}}, \"141\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\t😀\", \"prepend_text\": \"a,\", \"append_text\": \"
 猫\\u001c\", \"clip\": [\"4\", 1]}}, \"140\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"141\", 0]}}, \"139\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"140\", 0]}}, \"136\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"137\", 0], \"negative\": [\"139\", 0], \"upscaled_image\": [\"134\", 0]}}, \"142\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"136\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (ConditioningCombine).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "snow\t"}}, "resolution": {"node": {"class_type": "ConditioningCombine", "id": "117"}, "reason": "Combined conditioning has different texts", "reason_code": "composite", "sampler_id": "110", "state": "unresolved"}}, "name": "select-fuzz-0-42", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u3000caf\\u00e9\\u001c\", \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"102\", 0]}}, \"103\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\tdetailed fur\\ufeff\", \"negative_text\": \"\\ufeffcaf\\u00e9\", \"prepend_text\": \"\\u3000detailed fur\\u0085\", \"append_text\": \"\\t\\ud83d\\ude00\\ufeff\\u732b\"}}, \"104\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"104\", 0]}}, \"105\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"109\": {\"class_type\": \"StringConstant\", \"inputs\": {\"text\": \"\\u001ccaf\\u00e9\\t\"}}, \"108\": {\"class_type\": \"StringConstant\", \"inputs\": {\"text\": [\"109\", 0]}}, \"107\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"108\", 0], \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"upscaled_image\": [\"105\", 0]}}, \"114\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"snow\\t\", \"clip\": [\"4\", 1]}}, \"113\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"114\", 0]}}, \"112\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"113\", 0]}}, \"111\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"112\", 0]}}, \"118\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\tfox\\u001c\", \"clip\": [\"4\", 1]}}, \"119\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" detailed fur\\u001c\", \"clip\": [\"4\", 1]}}, \"117\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"118\", 0], \"conditioning_2\": [\"119\", 0]}}, \"120\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" fox\", \"negative_text\": \"\\u3000\\u0085\", \"prepend_text\": \"\\nsnow\\u3000\", \"append_text\": \" \\ud83d\\ude00\\u2028 \"}}, \"116\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"117\", 0], \"conditioning_2\": [\"120\", 1]}}, \"115\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"116\", 0]}}, \"110\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"106\", 0], \"model\": [\"4\", 0], \"positive\": [\"111\", 0], \"negative\": [\"115\", 0]}}, \"121\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"110\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-43", "records": {"parameters": " snow \n\n猫…\n café "}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "absent", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "😀 …snow 猫"}}, "resolution": {"node": null, "reason": "Negative input is absent", "reason_code": null, "sampler_id": "103", "state": "absent"}}, "name": "select-fuzz-0-44", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u0085snow \", \"prepend_text\": \"\\t\\ud83d\\ude00\\n\", \"append_text\": \"\\t\\u732b\\u3000\", \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"103\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\ufeff\\u732b\", \"strip_newlines\": true}}, \"106\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"107\", 0]}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}, \"104\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"105\", 0], \"text_l\": [\"105\", 0]}}, \"108\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u0085snow\\u001c\", \"clip\": [\"4\", 1]}}, \"109\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"104\", 0], \"negative\": [\"108\", 0], \"latent_image\": [\"5\", 0]}}, \"110\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"102\", 0]}}, \"111\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"110\", 0]}}, \"112\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"113\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"112\", 0]}}, \"114\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"115\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"114\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": "zeroed-conditioning", "status": "resolved", "text": ""}, "positive": {"source": "graph-inferred", "status": "resolved", "text": ", 猫"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "108", "state": "resolved"}}, "name": "select-fuzz-0-45", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\n\\u732b \", \"strip_newlines\": false}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \" \\ufeff\", \"negative_text\": \"\\u001c\\n\"}}, \"106\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \"\\u3000\\ud83d\\ude00\\u3000\", \"prepend_text\": \" \\u732b\\u0085\", \"append_text\": \"\\u001cfox\\u001c\", \"clip\": [\"4\", 1]}}, \"105\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"106\", 0]}}, \"104\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"105\", 0]}}, \"103\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"104\", 0]}}, \"107\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"109\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"110\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"109\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"108\", 0]}}, \"112\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"111\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-46", "records": {"parameters": "\u001c… 
 detailed fur Negative prompt: fox…\n"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Expected a typed graph link or text input", "reason_code": "malformed", "sampler_id": "109", "state": "unresolved"}}, "name": "select-fuzz-0-47", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"108\": {\"records\": [{\"text\": \"\\u2028 detailed fur\\t\", \"negative_text\": \"\\tfox\\u001c\", \"prepend_text\": \"\\ufeff\", \"append_text\": \"\\u732b \\u732b\", \"positive_text\": \"\\u001c\\u732b\\u2028 \", \"negative_effective_text\": \"\\tfox\\u001c\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": \" café \"}}, \"103\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"104\", 0]}}, \"106\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\nfox
 \", \"string_4\": \"snow\\nsnow\", \"inputcount\": 4, \"delimiter\": \" \", \"return_list\": false}}, \"105\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": [\"106\", 0], \"strip_newlines\": false}}, \"102\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"103\", 0], \"string_b\": [\"105\", 0], \"delimiter\": \", \"}}, \"101\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"102\", 0], \"clip\": [\"4\", 1]}}, \"108\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"
 detailed fur\\t\", \"negative_text\": \"\\tfox\\u001c\", \"prepend_text\": \" \", \"append_text\": \"
 猫 猫\"}}, \"107\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"108\", 0]}}, \"109\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"111\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\nsnow\\n\", \"text_l\": \"\\nsnow\\n\"}}, \"110\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"111\", 0]}}, \"113\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"…detailed fur \", \"strip_newlines\": false}}, \"112\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"113\", 0], \"prepend_text\": \"snow\\t\", \"append_text\": \"
 😀\\u001cdetailed fur\", \"clip\": [\"4\", 1]}}, \"114\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"110\", 0], \"negative\": [\"112\", 0], \"latent_image\": [\"5\", 0]}}, \"115\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"109\", 0]}}, \"116\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"114\", 0]}}, \"117\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"116\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-48", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"105\": {\"records\": [{\"text\": \"\\u3000\\tfox\", \"negative_text\": \"\\u2028 detailed fur\\u0085a,\", \"prepend_text\": \"detailed fur\", \"append_text\": \"detailed fur\\ufeff\", \"positive_text\": \"\\nsnow\\u2028 \", \"negative_effective_text\": \"\\u2028 detailed fur\\u0085a,\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\ta, 😀\", \"strip_newlines\": false}}, \"103\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"103\", 0], \"prepend_text\": \"\\nsnow\\u001c猫\", \"negative_text\": \"\\ncafé\"}}, \"101\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"102\", 0], \"conditioning_2\": [\"102\", 0]}}, \"105\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" \\tfox\", \"negative_text\": \"
 detailed fur…a,\", \"prepend_text\": \"
 detailed fur\", \"append_text\": \"detailed fur\"}}, \"106\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"107\", 0]}}, \"108\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"106\", 0]}}, \"109\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"108\", 0]}}, \"110\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"108\", 0]}}, \"111\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"112\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"111\", 0]}}, \"115\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"
 café\\t\", \"prepend_text\": \"\\n😀
 \", \"append_text\": \"猫\", \"clip\": [\"4\", 1]}}, \"116\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"\\u001c\\u001ca,\"}}, \"114\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 0], \"on_true\": [\"115\", 0], \"on_false\": [\"116\", 0]}}, \"113\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"114\", 0], \"upscaled_image\": [\"111\", 0]}}, \"117\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"113\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-49", "records": {"parameters": "Negative Template: n Steps: x\r\n"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-50", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"101\": {\"records\": [{\"text\": \"\\u2028 snow\\u3000\", \"negative_text\": \" detailed fur\\ufeff\", \"prepend_text\": \"\", \"append_text\": \"detailed fur\", \"positive_text\": \"\\u001c\\ud83d\\ude00\\t\", \"negative_effective_text\": \" detailed fur\\ufeff\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"
 snow \", \"negative_text\": \" detailed fur\", \"prepend_text\": \" \\t\", \"append_text\": \"\\tdetailed fur
 \"}}, \"104\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\n
 \", \"negative_text\": \"
 fox\\n\", \"prepend_text\": \"
 猫\\u001ca,\", \"append_text\": \"\\u001cdetailed fur\\t😀\"}}, \"103\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"104\", 0]}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"105\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"108\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"107\", 0]}}, \"109\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"107\", 0]}}, \"110\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"106\", 0]}}, \"114\": {\"class_type\": \"StringConstantMultiline\", \"inputs\": {\"string\": \"\\ncafé\", \"strip_newlines\": true}}, \"113\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"detailed fur 猫\", \"string_b\": [\"114\", 0], \"delimiter\": \", \"}}, \"112\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"113\", 0], \"prepend_text\": \"\\nfox \", \"append_text\": \" detailed fur \", \"clip\": [\"4\", 1]}}, \"111\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"110\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"112\", 0]}}, \"115\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"111\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "107", "state": "unresolved"}}, "name": "select-fuzz-0-51", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \" a, \", \"prepend_text\": \"…猫\", \"negative_text\": \"…\\n\"}}, \"105\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" detailed fur\\n\", \"clip\": [\"4\", 1]}}, \"103\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"104\", 0], \"conditioning_2\": [\"105\", 0]}}, \"102\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"103\", 0]}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"106\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"
 \\tfox\", \"negative_text\": \"
 \", \"prepend_text\": \"…café \", \"append_text\": \"…\\n\"}}, \"107\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"106\", 1], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"107\", 0]}}, \"109\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"108\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Sampler stages have different prompts", "reason_code": "multistage-differs", "sampler_id": "108", "state": "ambiguous"}}, "name": "select-fuzz-0-52", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\u001c
 \", \"prepend_text\": \"snow\\u001cdetailed fur\", \"append_text\": \"a,\"}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"103\", 0], \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"104\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": \"\\ncafé
 snow\", \"prepend_text\": \"\\tfox
 \", \"negative_text\": \"
 
 \"}}, \"105\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"107\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"106\", 0]}}, \"109\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" snow\", \"clip\": [\"4\", 1]}}, \"112\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\u001cfox\\t\", \"text_l\": \"\\u001cfox\\t\"}}, \"111\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"112\", 0]}}, \"110\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"111\", 0]}}, \"108\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"109\", 0], \"negative\": [\"110\", 0], \"upscaled_image\": [\"106\", 0]}}, \"113\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"missing\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-53", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"124\": {\"records\": [{\"text\": \"a,\\n\", \"negative_text\": \"\\n\\u2028 \", \"prepend_text\": \"a,\", \"append_text\": \"detailed fur\", \"positive_text\": \"\\ncaf\\u00e9\\u0085\", \"negative_effective_text\": \"\\n\\u2028 \"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\ufeff\"}}, \"105\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"\\u2028 caf\\u00e9 \", \"string_b\": \"\\u0085\\u732b\\u2028 \", \"delimiter\": \" \"}}, \"104\": {\"class_type\": \"TextInput\", \"inputs\": {\"string\": [\"105\", 0]}}, \"103\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"104\", 0]}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": [\"103\", 0], \"clip\": [\"4\", 1]}}, \"106\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"108\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\tcaf\\u00e9\\u0085\\ud83d\\ude00\", \"negative_text\": \"\\u3000detailed fur\\u2028 caf\\u00e9\", \"prepend_text\": \" a,\\u3000caf\\u00e9\", \"append_text\": \"detailed fur\\u2028 \\ud83d\\ude00\"}}, \"110\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"fox\\n\", \"clip\": [\"4\", 1]}}, \"112\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\u001c\\ud83d\\ude00\\ufeffsnow\"}}, \"113\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u001c\\ud83d\\ude00 \", \"prepend_text\": \"\\u2028 snow\\u0085\", \"append_text\": \"\\u001ca,\\ud83d\\ude00\", \"clip\": [\"4\", 1]}}, \"111\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"112\", 0], \"on_false\": [\"113\", 0]}}, \"109\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": false, \"on_true\": [\"110\", 0], \"on_false\": [\"111\", 0]}}, \"107\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"108\", 0], \"conditioning_2\": [\"109\", 0]}}, \"114\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"107\", 0], \"latent_image\": [\"5\", 0]}}, \"115\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"116\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"106\", 0]}}, \"117\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"116\", 0]}}, \"118\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"114\", 0]}}, \"119\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"118\", 0]}}, \"120\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"115\", 0]}}, \"121\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"120\", 0]}}, \"124\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"a,\\n\", \"negative_text\": \"\\n\\u2028 \", \"prepend_text\": \"\\na,\\u0085\", \"append_text\": \"detailed fur \"}}, \"126\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"\\nsnow\\u3000\"}}, \"125\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"126\", 0], \"conditioning_2\": [\"126\", 0]}}, \"123\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"124\", 1], \"conditioning_2\": [\"125\", 0]}}, \"122\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"120\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"123\", 0]}}, \"127\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"122\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Multiple sampler branches", "reason_code": null, "sampler_id": null, "state": "ambiguous"}}, "name": "select-fuzz-0-54", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"122\": {\"records\": [{\"text\": \"\\u0085\\u732b\\t\", \"negative_text\": \"\\u2028 caf\\u00e9\\u3000\", \"prepend_text\": \"\\ud83d\\ude00\\u3000a,\", \"append_text\": \"caf\\u00e9\", \"positive_text\": \" \\ud83d\\ude00\\u3000\", \"negative_effective_text\": \"\\u2028 caf\\u00e9\\u3000\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"102\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\ta,\", \"clip\": [\"4\", 1]}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"106\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"café \", \"prepend_text\": \"…a, café\", \"negative_text\": \"…a,\\n😀\"}}, \"105\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"106\", 0]}}, \"108\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"猫\", \"text_l\": \"猫\"}}, \"109\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\n猫\\n\", \"text_l\": \"\\n猫\\n\"}}, \"107\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"108\", 0], \"on_false\": [\"109\", 0]}}, \"104\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"105\", 0], \"on_false\": [\"107\", 0]}}, \"110\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"…fox…snow\"}}, \"103\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"104\", 0], \"conditioning_2\": [\"110\", 0]}}, \"111\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"103\", 0], \"latent_image\": [\"5\", 0]}}, \"113\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \"a,\"}}, \"112\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"113\", 0]}}, \"117\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_b\": \"猫\", \"text_d\": \"\", \"text_a\": \"a,
 \", \"clean_whitespace\": \"true\"}}, \"116\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"😀 fox\", \"string_b\": [\"117\", 0], \"delimiter\": \"\"}}, \"115\": {\"class_type\": \"PrimitiveString\", \"inputs\": {\"value\": [\"116\", 0]}}, \"114\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"115\", 0], \"prepend_text\": \"\", \"negative_text\": \"\\u001cdetailed fur\\n\"}}, \"118\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"112\", 0], \"negative\": [\"114\", 0], \"latent_image\": [\"5\", 0]}}, \"119\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"112\", 0], \"negative\": [\"114\", 0], \"latent_image\": [\"118\", 0]}}, \"120\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"111\", 0]}}, \"122\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"…猫\\t\", \"negative_text\": \"
 café \", \"prepend_text\": \" 😀 a,\", \"append_text\": \" café \"}}, \"121\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"120\", 0], \"model\": [\"4\", 0], \"positive\": [\"112\", 0], \"negative\": [\"122\", 0]}}, \"123\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"121\", 0]}}, \"124\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"118\", 0]}}, \"125\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"124\", 0]}}, \"126\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"119\", 0]}}, \"128\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": \" 猫 \", \"prepend_text\": \"猫\\u001c😀\", \"append_text\": \" 猫\\tdetailed fur\", \"clip\": [\"4\", 1]}}, \"132\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"
 \", \"clip\": [\"4\", 1]}}, \"131\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"132\", 0]}}, \"130\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"131\", 0]}}, \"129\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"130\", 0], \"conditioning_2\": [\"130\", 0]}}, \"127\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"126\", 0], \"model\": [\"4\", 0], \"positive\": [\"128\", 0], \"negative\": [\"129\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Prompt metadata in this file is malformed.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "A1111 settings footer is not unique", "reason_code": "malformed", "sampler_id": null, "state": "unresolved"}}, "name": "select-fuzz-0-55", "records": {"parameters": "…😀\t\r\nTemplate: t\rSteps: x Steps:٣, a\r\t\n\r"}}, {"evidence": {"prompts": {"negative": {"source": "graph-inferred", "status": "resolved", "text": "fox 😀 detailed fur 猫\u001c猫"}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "detailed fur, fox 
 😀\u001c, … a,"}}, "resolution": {"node": null, "reason": "", "reason_code": null, "sampler_id": "106", "state": "resolved"}}, "name": "select-fuzz-0-56", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"104\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": \"
 😀\\u001c\", \"string_b\": \"… \", \"delimiter\": \", \"}}, \"103\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": [\"104\", 0], \"prepend_text\": \" fox \", \"append_text\": \"a,\"}}, \"102\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"103\", 0]}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"detailed fur\\n\", \"negative_text\": \"😀
 \"}}, \"105\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" detailed fur \", \"negative_text\": \"\\u001ca,…café\", \"prepend_text\": \"
 fox 😀\", \"append_text\": \"
 猫\\u001c猫\"}}, \"106\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"105\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"missing\", 0]}}, \"108\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"107\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Prompt combines several texts (CLIPTextEncodeSDXL).", "source": null, "status": "unresolved", "text": null}, "positive": {"source": "graph-inferred", "status": "resolved", "text": "detailed fur, snow 
 a,
  a,"}}, "resolution": {"node": {"class_type": "CLIPTextEncodeSDXL", "id": "104"}, "reason": "Encoder parts have different texts", "reason_code": "composite", "sampler_id": "105", "state": "unresolved"}}, "name": "select-fuzz-0-57", "records": {"comfyassets_prompt_pairs": "{\"version\": 1, \"nodes\": {\"107\": {\"records\": [{\"text\": \" snow\\u0085\", \"negative_text\": \"\\u001c\\u732b\\ufeff\", \"prepend_text\": \"fox\", \"append_text\": \"a,\\ufeff\\ud83d\\ude00\", \"positive_text\": \"\\ufeffcaf\\u00e9\\ufeff\", \"negative_effective_text\": \"\\u001c\\u732b\\ufeff\"}]}}}", "prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\u0085snow\\ufeff\", \"string_2\": \"\\u2028 a,\\u2028 \", \"inputcount\": 2, \"delimiter\": \" \", \"return_list\": false}}, \"102\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"103\", 0], \"string_b\": \"\\u3000a, \", \"delimiter\": \"\"}}, \"101\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"102\", 0], \"prepend_text\": \"\\ufeffdetailed fur\\u2028 \", \"negative_text\": \"\\u001ccaf\\u00e9\\t\"}}, \"104\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\na,\\u3000\", \"text_l\": \" \"}}, \"105\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"104\", 0], \"latent_image\": [\"5\", 0]}}, \"107\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \" snow\\u0085\", \"negative_text\": \"\\u001c\\u732b\\ufeff\", \"prepend_text\": \"\\u001c\\u0085fox\", \"append_text\": \"\\u0085a,\\ufeff\\ud83d\\ude00\"}}, \"106\": {\"class_type\": \"Reroute\", \"inputs\": {}}, \"111\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\ncaf\\u00e9\\ufeffa,\", \"text_l\": \"\\u3000a,\\n\"}}, \"110\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"111\", 0]}}, \"109\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"110\", 0]}}, \"108\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"109\", 0]}}, \"112\": {\"class_type\": \"SamplerCustom\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"106\", 0], \"negative\": [\"108\", 0], \"latent_image\": [\"5\", 0]}}, \"113\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"105\", 0]}}, \"114\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"113\", 0]}}, \"115\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"112\", 0]}}, \"119\": {\"class_type\": \"JoinStringMulti\", \"inputs\": {\"string_1\": \"\\u0085fox\\t\", \"inputcount\": 1, \"delimiter\": \" \", \"return_list\": false}}, \"118\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"119\", 0], \"text_l\": [\"119\", 0]}}, \"121\": {\"class_type\": \"PrimitiveStringMultiline\", \"inputs\": {\"value\": \"\\u0085\\n\"}}, \"120\": {\"class_type\": \"PromptManagerFocused\", \"inputs\": {\"text\": [\"121\", 0], \"prepend_text\": \"\\u0085detailed fur\\u3000\", \"append_text\": \"\\t\", \"clip\": [\"4\", 1]}}, \"117\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": [\"4\", 1], \"on_true\": [\"118\", 0], \"on_false\": [\"120\", 0]}}, \"122\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\t\\u732b \", \"prepend_text\": \"\\u3000\\u732b\\u2028 \", \"negative_text\": \"\\tdetailed fur\\ta,\"}}, \"116\": {\"class_type\": \"FaceDetailer\", \"inputs\": {\"image\": [\"115\", 0], \"model\": [\"4\", 0], \"positive\": [\"117\", 0], \"negative\": [\"122\", 0]}}, \"124\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\u2028 snow \", \"text_l\": \"\"}}, \"125\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": \"\\u001c\\u732b\\u0085caf\\u00e9\", \"prepend_text\": \"\\ufeffcaf\\u00e9\\u0085\", \"negative_text\": \"\\n\\u732b\\t\"}}, \"123\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"116\", 0], \"model\": [\"4\", 0], \"positive\": [\"124\", 0], \"negative\": [\"125\", 0]}}, \"126\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"123\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}, "positive": {"message": "Positive prompt is empty.", "source": null, "status": "unresolved", "text": null}}, "resolution": {"node": null, "reason": "Positive prompt is empty", "reason_code": null, "sampler_id": "108", "state": "unresolved"}}, "name": "select-fuzz-0-58", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"101\": {\"class_type\": \"PromptManager\", \"inputs\": {\"text\": \"\\u001csnow\\n\", \"prepend_text\": \"\\u3000detailed fur\\ufeffsnow\", \"append_text\": \"\\u0085\\u3000\", \"clip\": [\"4\", 1]}}, \"102\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \" \\ufeff\"}}, \"103\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"104\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"102\", 0], \"latent_image\": [\"5\", 0]}}, \"105\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"103\", 0]}}, \"106\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"105\", 0]}}, \"107\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"112\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" fox a,\", \"clip\": [\"4\", 1]}}, \"111\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"112\", 0]}}, \"114\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \" detailed fur\\u001c\", \"clip\": [\"4\", 1]}}, \"113\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"114\", 0]}}, \"110\": {\"class_type\": \"easy ifElse\", \"inputs\": {\"boolean\": true, \"on_true\": [\"111\", 0], \"on_false\": [\"113\", 0]}}, \"109\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"110\", 0]}}, \"117\": {\"class_type\": \"Text Concatenate\", \"inputs\": {\"text_a\": \" \\ud83d\\ude00\\u3000\", \"text_b\": \"\\ncaf\\u00e9 \", \"text_d\": \"\\n\\ud83d\\ude00\\u001c\", \"clean_whitespace\": \"true\"}}, \"118\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"\\u001ccaf\\u00e9 \\u732b\", \"prepend_text\": \"\\u2028 \\u732b\\n\\u732b\", \"append_text\": \"\\ufeff \"}}, \"116\": {\"class_type\": \"StringConcatenate\", \"inputs\": {\"string_a\": [\"117\", 0], \"string_b\": [\"118\", 0], \"delimiter\": \", \"}}, \"115\": {\"class_type\": \"PromptManagerPositive\", \"inputs\": {\"text\": [\"116\", 0], \"prepend_text\": \"\\u2028 caf\\u00e9\", \"negative_text\": \"\\tcaf\\u00e9\\u3000\"}}, \"108\": {\"class_type\": \"DetailerForEach\", \"inputs\": {\"image\": [\"107\", 0], \"model\": [\"4\", 0], \"positive\": [\"109\", 0], \"negative\": [\"115\", 0]}}}"}}, {"evidence": {"prompts": {"negative": {"source": null, "status": "ambiguous", "text": null}, "positive": {"source": null, "status": "ambiguous", "text": null}}, "resolution": {"node": null, "reason": "Sampler stages have different prompts", "reason_code": "multistage-differs", "sampler_id": "113", "state": "ambiguous"}}, "name": "select-fuzz-0-59", "records": {"prompt": "{\"4\": {\"class_type\": \"CheckpointLoaderSimple\", \"inputs\": {\"ckpt_name\": \"m\"}}, \"5\": {\"class_type\": \"EmptyLatentImage\", \"inputs\": {\"width\": 64}}, \"103\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \"…猫…\", \"prepend_text\": \"a,\", \"append_text\": \"
 detailed fur\\u001c\"}}, \"102\": {\"class_type\": \"PromptManagerV2\", \"inputs\": {\"text\": [\"103\", 0], \"prepend_text\": \"\\t猫\", \"negative_text\": \"\\n\\u001c\"}}, \"101\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"102\", 0]}}, \"104\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"106\": {\"class_type\": \"PromptSearchList\", \"inputs\": {\"text\": \"fox\"}}, \"108\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": \"\\u001c😀 \", \"text_l\": \"\\nfox…\"}}, \"107\": {\"class_type\": \"FluxGuidance\", \"inputs\": {\"conditioning\": [\"108\", 0]}}, \"105\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"106\", 0], \"conditioning_2\": [\"107\", 0]}}, \"109\": {\"class_type\": \"FancyEncoder\", \"inputs\": {\"text\": \" 😀a,\"}}, \"110\": {\"class_type\": \"KSamplerAdvanced\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"105\", 0], \"negative\": [\"109\", 0], \"latent_image\": [\"5\", 0]}}, \"111\": {\"class_type\": \"KSampler\", \"inputs\": {\"seed\": 1, \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"latent_image\": [\"5\", 0]}}, \"112\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"104\", 0]}}, \"115\": {\"class_type\": \"PromptManagerPair\", \"inputs\": {\"text\": \"\\u001ccafé\", \"negative_text\": \"\\u001c猫café\", \"prepend_text\": \"café\\n\", \"append_text\": \"…😀 \"}}, \"114\": {\"class_type\": \"Reroute\", \"inputs\": {\"value\": [\"115\", 0]}}, \"119\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"a,\\u001c\", \"clip\": [\"4\", 1]}}, \"120\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001c猫\\u001c\", \"clip\": [\"4\", 1]}}, \"118\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"119\", 0], \"conditioning_2\": [\"120\", 0]}}, \"122\": {\"class_type\": \"CLIPTextEncode\", \"inputs\": {\"text\": \"\\u001cdetailed fursnow\", \"clip\": [\"4\", 1]}}, \"121\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"122\", 0], \"conditioning_2\": [\"122\", 0]}}, \"117\": {\"class_type\": \"ConditioningCombine\", \"inputs\": {\"conditioning_1\": [\"118\", 0], \"conditioning_2\": [\"121\", 0]}}, \"116\": {\"class_type\": \"ConditioningZeroOut\", \"inputs\": {\"conditioning\": [\"117\", 0]}}, \"113\": {\"class_type\": \"UltimateSDUpscaleNoUpscale\", \"inputs\": {\"model\": [\"4\", 0], \"positive\": [\"114\", 0], \"negative\": [\"116\", 0], \"upscaled_image\": [\"112\", 0]}}, \"123\": {\"class_type\": \"SaveImage\", \"inputs\": {\"images\": [\"113\", 0]}}, \"124\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"110\", 0]}}, \"125\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"124\", 0]}}, \"126\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"124\", 0]}}, \"127\": {\"class_type\": \"VAEDecode\", \"inputs\": {\"samples\": [\"111\", 0]}}, \"128\": {\"class_type\": \"PreviewAny\", \"inputs\": {\"images\": [\"127\", 0]}}, \"131\": {\"class_type\": \"PromptManagerText\", \"inputs\": {\"text\": \" fox\", \"prepend_text\": \"\\ndetailed fur…\", \"append_text\": \" \\u001c\"}}, \"130\": {\"class_type\": \"CLIPTextEncodeSDXL\", \"inputs\": {\"text_g\": [\"131\", 0], \"text_l\": [\"131\", 0]}}, \"129\": {\"class_type\": \"UltimateSDUpscale\", \"inputs\": {\"image\": [\"127\", 0], \"model\": [\"4\", 0], \"positive\": [\"101\", 0], \"negative\": [\"130\", 0]}}, \"132\": {\"class_type\": \"PreviewImage\", \"inputs\": {\"images\": [\"129\", 0]}}}"}}], "version": 2} diff --git a/tests/js/support/local-inspect-oracle.mjs b/tests/js/support/local-inspect-oracle.mjs index 61711ce..c85d1d1 100644 --- a/tests/js/support/local-inspect-oracle.mjs +++ b/tests/js/support/local-inspect-oracle.mjs @@ -14,6 +14,11 @@ // the carrier rule alone, as the server selects from ffprobe's tag map. // A {records} entry (records null = an unreadable file) answers // {classified: null, result: null, metadata} for the projection alone. +// A {mode: 'resolve'} entry (PR L3) answers {evidence}: resolveLocalEvidence of its {records} texts +// with the repository semantics table. With a {path} it reads the file locally and also answers +// {facts} (and {unreadable: true} with the server's unreadable evidence when nothing could be read): +// extractGenerationFacts on the local payload through projectInspectionPayload, exactly as +// tests/js/support/inspection-parity-facts.mjs reads the server's response for vectors.json. import fs from 'node:fs'; import path from 'node:path'; import { createRequire } from 'node:module'; @@ -28,6 +33,22 @@ const web = path.join(here, '..', '..', '..', 'web', 'js', 'workspace'); const { selectVideoCarrier } = await import(moduleUrl(path.join(web, 'local-video.mjs'))); const { projectMetadata } = await import(moduleUrl(path.join(web, 'local-projection.mjs'))); const { readLocalFile, toInspectionRead } = await import(moduleUrl(path.join(web, 'local-inspection.mjs'))); +const { resolveLocalEvidence, compileSemantics, unreadableEvidence } = await import(moduleUrl(path.join(web, 'local-resolver.mjs'))); +const { buildLocalPayload } = await import(moduleUrl(path.join(web, 'local-inspection.mjs'))); +const { projectInspectionPayload } = await import(moduleUrl(path.join(web, 'inspection-state.mjs'))); +const semantics = compileSemantics(JSON.parse(fs.readFileSync(path.join(here, '..', '..', '..', 'web', 'js', 'inspection-semantics.json'), 'utf8'))); +const { extractGenerationFacts } = require(path.join(here, '..', '..', '..', 'web', 'js', 'comfy-metadata.js')); + +/** The local evidence for one set of record texts. */ +const resolved = records => ({ evidence: resolveLocalEvidence(records, semantics) }); + +/** The local wire's evidence and six facts for one read (no legacy fill, as in the vectors' own harness). */ +function localPayload(read, file, classification) { + const payload = buildLocalPayload({ read, file, classification, semantics }); + const record = projectInspectionPayload(payload, { kind: 'local-file', key: 'local:1', path: file.name }, null, extractGenerationFacts); + const facts = Object.fromEntries(Object.entries(record.generation).map(([field, fact]) => [field, { status: fact.status, value: fact.value }])); + return { evidence: { prompts: payload.prompts, resolution: payload.resolution }, facts }; +} const selectionRead = (selection) => selection.status === 'complete' ? { records: selection.records, record_formats: selection.record_formats, carrierText: selection.carrierText, limited: selection.limited } : null; @@ -37,6 +58,19 @@ for await (const chunk of process.stdin) chunks.push(chunk); const output = {}; for (const entry of JSON.parse(Buffer.concat(chunks).toString('utf8'))) { const { name } = entry; + if (entry.mode === 'resolve') { + if (entry.records !== undefined) { output[name] = resolved(entry.records); continue; } + const blob = await fs.openAsBlob(entry.path); + const { classification, result } = await readLocalFile(blob, { pngMetadata }); + const read = classification === null ? null : toInspectionRead(classification, result).read; + if (classification === null) { output[name] = { unreadable: true }; continue; } + // The evidence is the local wire's own (buildLocalPayload), and it equals resolveLocalEvidence of the records. + const local = localPayload(result, { name: path.basename(entry.path), size: blob.size }, classification); + const direct = read === null ? unreadableEvidence() : resolved(read.records).evidence; + if (JSON.stringify(direct) !== JSON.stringify(local.evidence)) throw new Error(`${name}: the wire's roles are not the resolver's`); + output[name] = read === null ? { unreadable: true, ...local } : local; + continue; + } if (entry.records !== undefined) { const read = entry.records === null ? null : { records: entry.records, diff --git a/tests/js/workspace-file-inspector.test.js b/tests/js/workspace-file-inspector.test.js index cb722ff..6371f59 100644 --- a/tests/js/workspace-file-inspector.test.js +++ b/tests/js/workspace-file-inspector.test.js @@ -215,3 +215,151 @@ test('none and unavailable render no image chips', async () => { assert.deepEqual(inspectorTagChips(tagged({state, tags:[]}, {status:'none', tags:[], tags_scope:null}), {filterable:true}), []); } }); + +// LI-4 (D117): "Copy settings summary" after the six facts of the full inspector consolidates the legacy metadata +// page's COPY ALL (web/metadata.html copyAllData). The legacy template is read from that page itself and run on the +// legacy parse, so the summary's text is the legacy page's, line for line, wherever the two agree on the values. +const METADATA_PAGE = fs.readFileSync(new URL('../../web/metadata.html', import.meta.url), 'utf8'); +function legacyCopyAll(params) { + const template = METADATA_PAGE.match(/const allData = `([\s\S]*?)`;/)[1]; + return new Function('currentWorkflowData', `return \`${template}\`;`)(params); +} +const legacyParams = record => ComfyMetadata.extractGenerationParams({prompt:record.metadata.prompt_graph.status === 'parsed' ? record.metadata.prompt_graph.value : null, + workflow:record.metadata.workflow_graph.status === 'parsed' ? record.metadata.workflow_graph.value : null}); + +/** + * Each summary line against the legacy page's, allowing only the recorded differences (D117): a number keeps the + * inspector's (the server's) spelling ("8.0" where the legacy page wrote 8); a fact the legacy parse left "Unknown" may + * be known; and a negative the #249 ZeroOut guard zeroed reads "No negative prompt found" where the legacy parse read + * the positive's text through the zero-out. + */ +function assertLegacySummary(summary, legacy, record) { + const lines = summary.split('\n'), expected = legacy.split('\n'); + assert.deepEqual(lines.map(line => line.split(':')[0]), expected.map(line => line.split(':')[0]), 'the legacy labels, in order'); + lines.forEach((line, index) => { + if (line === expected[index]) return; + const [label, value] = [line.slice(0, line.indexOf(': ')), line.slice(line.indexOf(': ') + 2)]; + const old = expected[index].slice(label.length + 2); + if (label === 'Negative Prompt' && record.prompts.negative?.source === 'zeroed-conditioning' && value === 'No negative prompt found') return; + if (old === 'Unknown' && !/Prompt$/.test(label)) return; + assert.ok(value.trim() !== '' && Number(value) === Number(old), `${label}: "${value}" differs from the legacy "${old}"`); + }); +} + +test('settings summary is the legacy COPY ALL text for a local file', async () => { + const {settingsSummary} = await load(); + assert.equal(typeof settingsSummary, 'function', 'settingsSummary is exported'); + const record = await localRecord(localPng('fox.png')); + assertLegacySummary(settingsSummary(record), legacyCopyAll(legacyParams(record)), record); + assert.equal(settingsSummary(record), ['Checkpoint: synthetic-v1.safetensors', 'Positive Prompt: a red fox in snow, detailed fur', + 'Negative Prompt: blurry, lowres', 'Steps: 20', 'CFG Scale: 8.0', 'Sampler: euler', 'Seed: 7'].join('\n')); + // Every parity PNG read in this browser: the legacy page's text but for the recorded differences, and exactly the + // legacy text for most of them (f09 among them: the server is ambiguous, so the record shows the legacy fill). + const exact = []; + for (const name of fs.readdirSync(PARITY).filter(item => item.endsWith('.png')).sort()) { + const parity = await localRecord(new File([fs.readFileSync(new URL(name, PARITY))], name)); + const summary = settingsSummary(parity), legacy = legacyCopyAll(legacyParams(parity)); + assertLegacySummary(summary, legacy, parity); + if (summary === legacy) exact.push(name); + } + assert.ok(exact.includes('f09.png')); + assert.deepEqual(fs.readdirSync(PARITY).filter(item => item.endsWith('.png') && !exact.includes(item)).sort(), ['f01b.png', 'f17.png', 'f23.png']); +}); + +test('settings summary uses the legacy placeholders for what the record does not know', async () => { + const {settingsSummary} = await load(); + const unknown = {...record(), prompts:{positive:{status:'unresolved'}, negative:{status:'ambiguous'}}, generation:{}}; + assert.equal(settingsSummary(unknown), legacyCopyAll({}).replace('Positive Prompt: undefined', 'Positive Prompt: No prompt found') + .replace('Negative Prompt: undefined', 'Negative Prompt: No negative prompt found')); + assert.equal(settingsSummary(unknown), ['Checkpoint: Unknown', 'Positive Prompt: No prompt found', 'Negative Prompt: No negative prompt found', + 'Steps: Unknown', 'CFG Scale: Unknown', 'Sampler: Unknown', 'Seed: Unknown'].join('\n')); + // A server answer is shown as the inspector shows it: known facts verbatim, every other state the legacy "Unknown". + const server = {...record(), prompts:{positive:{status:'resolved', text:'a\n猫'}, negative:{status:'resolved', text:''}}, generation:{ + model:{status:'known', value:'m.safetensors'}, steps:{status:'not-recorded', value:null}, cfg:{status:'known', value:'6.50'}, + sampler:{status:'ambiguous', value:null}, seed:{status:'known', value:'9007199254740993'}, scheduler:{status:'known', value:'karras'}}}; + assert.equal(settingsSummary(server), ['Checkpoint: m.safetensors', 'Positive Prompt: a\n猫', 'Negative Prompt: No negative prompt found', + 'Steps: Unknown', 'CFG Scale: 6.50', 'Sampler: Unknown', 'Seed: 9007199254740993'].join('\n')); +}); + +/** The full inspector with a toast node and `clipboard` as `navigator.clipboard`; returns the summary button. */ +function renderSummary(record, {variant = 'full', clipboard} = {}) { + const f = mountedDom(), scope = createScope(), fallbacks = [], toast = new f.Node('div'); + f.doc.getElementById = id => id === 'workspace-toast' ? toast : null; + const previous = Object.getOwnPropertyDescriptor(globalThis, 'navigator'); + Object.defineProperty(globalThis, 'navigator', {configurable:true, value:clipboard === undefined ? {} : {clipboard}}); + const view = mountFileInspector(f.container, {sender:{open() {}}, parentScope:scope, variant, copyFallback:(text, options) => fallbacks.push({text, ...options})}); + view.setState({loading:false, error:false, record}); + const button = f.walk(f.container, n => n.tagName === 'button' && n.textContent === 'Copy settings summary')[0] ?? null; + return {f, button, toast, fallbacks, scope, done() { + view.dispose(); scope.dispose(); f.restore(); + if (previous) Object.defineProperty(globalThis, 'navigator', previous); else delete globalThis.navigator; + }}; +} + +test('Copy settings summary follows the facts in the full inspector only', async () => { + const full = renderSummary(record()); + try { + assert.ok(full.button, 'the full inspector offers Copy settings summary'); + const inner = full.button.parent, index = inner.children.indexOf(full.button); + assert.equal(inner.children[index - 1].tagName, 'dl', 'it follows the six facts'); + assert.equal(inner.children[index + 1].tagName, 'details', 'File & provenance follows it'); + // M7: the D117 wrap rule targets this button by its class, never any button of a details block. + assert.equal(full.button.className, 'settings-summary'); + } finally { full.done(); } + const panel = renderSummary(record(), {variant:'panel'}); + try { assert.equal(panel.button, null, 'the Images side panel keeps the concept footer'); } finally { panel.done(); } +}); + +test('Copy settings summary copies the summary and shows the shared toast', async () => { + const {settingsSummary} = await load(), copied = []; + const view = renderSummary(record(), {clipboard:{writeText:async text => {copied.push(text);}}}); + try { + await view.button.listeners.get('click')[0].callback({target:view.button}); + assert.deepEqual(copied, [settingsSummary(record())]); + assert.equal(view.toast.textContent, 'Settings summary copied.'); + assert.equal(view.fallbacks.length, 0); + } finally { view.done(); } +}); + +test('Copy settings summary without a clipboard opens the select-to-copy fallback', async () => { + const {settingsSummary} = await load(); + for (const clipboard of [undefined, {writeText:async () => {throw new Error('Denied');}}]) { + const view = renderSummary(record(), {clipboard}); + try { + await view.button.listeners.get('click')[0].callback({target:view.button}); + assert.equal(view.fallbacks.length, 1); + assert.equal(view.fallbacks[0].text, settingsSummary(record())); + assert.equal(view.fallbacks[0].title, 'Copy settings summary'); + assert.equal(view.fallbacks[0].trigger, view.button); + assert.notEqual(view.toast.textContent, 'Settings summary copied.'); + } finally { view.done(); } + } +}); + +test('the inspector is busy while a read is loading, then not', async () => { + const f = mountedDom(), scope = createScope(); + const view = mountFileInspector(f.container, {sender:{open() {}}, parentScope:scope, variant:'full'}); + try { + view.setState({loading:true, error:false, record:null}); + assert.equal(f.container.getAttribute('aria-busy'), 'true'); + assert.ok(f.walk(f.container, n => n.textContent === 'Loading file details…').length); + view.setState({loading:false, error:false, record:record()}); + assert.equal(f.container.getAttribute('aria-busy'), null); + view.setState({loading:true, error:false, record:null}); + view.setState({loading:false, error:true, record:null}); + assert.equal(f.container.getAttribute('aria-busy'), null); + view.setState({loading:true, error:false, record:null}); + } finally { + view.dispose(); + assert.equal(f.container.getAttribute('aria-busy'), null, 'dispose clears the busy state'); + scope.dispose(); f.restore(); + } +}); + +test('the D117 wrap rule targets only the settings summary button', async () => { + const fs = await import('node:fs'); + const css = fs.readFileSync(new URL('../../web/js/workspace/workspace.css', import.meta.url), 'utf8'); + const rules = css.split('\n').filter(line => line.includes('D117')); + assert.deepEqual(rules.map(line => line.trim()), ['.ca-tools #viewer-details .settings-summary { white-space: normal; /* D117 */ }']); + assert.doesNotMatch(css, /#viewer-details > div > button/); +}); diff --git a/tests/js/workspace-local-inspection.test.js b/tests/js/workspace-local-inspection.test.js index 0769055..2994f9e 100644 --- a/tests/js/workspace-local-inspection.test.js +++ b/tests/js/workspace-local-inspection.test.js @@ -20,6 +20,16 @@ const { extractGenerationFacts } = ComfyMetadata; // The page loads both as scripts; the legacy fill and the PNG reader find them on the global. globalThis.PngMetadata = PngMetadata; globalThis.ComfyMetadata = ComfyMetadata; +// The page's API client and the node table it serves (local-semantics.mjs fetches it once). +const SEMANTICS = fs.readFileSync(path.join(here, "..", "..", "web", "js", "inspection-semantics.json"), "utf8"); +globalThis.window = { ApiClient: { resolveUrl: (value) => value } }; +// A test can hold the table request (`tableGate`) to stand for a slow or stalled proxy. +let tableGate = null; +globalThis.fetch = async (url) => { + if (url !== "/prompt_manager/js/inspection-semantics.json") throw new Error(`unexpected request ${url}`); + if (tableGate) await tableGate; + return new Response(SEMANTICS, { status: 200 }); +}; const m = await import("../../web/js/workspace/local-inspection.mjs").catch((error) => { if (error.code !== "ERR_MODULE_NOT_FOUND") throw error; return {}; @@ -59,6 +69,37 @@ test("contract", () => { assert.ok(Object.isFrozen(m.localFileAdapter)); }); +// M3: the first read waits for the page's one table request; an aborted, replaced or cleared selection must not. +test("a read waiting for the node table ends with its selection", async () => { + let release; + tableGate = new Promise((resolve) => { release = resolve; }); + try { + const file = pngFile("slow.png", [tEXt("prompt", PROMPT)]); + const aborted = new AbortController(); + const reading = m.localFileAdapter.read(await handleFor(file), { signal: aborted.signal }); + const settled = (promise) => Promise.race([promise.then(() => "resolved", (error) => error.name), new Promise((resolve) => setTimeout(() => resolve("pending"), 200))]); + await new Promise((resolve) => setTimeout(resolve, 20)); + aborted.abort(); + assert.equal(await settled(reading), "AbortError"); + // Through the controller: clearing the selection ends its read; nothing is published for it. + const controller = createInspectionController({ api: null, adapter: m.localFileAdapter, extractFacts: extractGenerationFacts }); + const states = []; + controller.subscribe((state) => states.push(state)); + const selected = controller.select(await handleFor(file)); + await new Promise((resolve) => setTimeout(resolve, 20)); + controller.clear(); + assert.equal(await settled(selected), "resolved"); + assert.ok(states.every((state) => state.record === null && state.error === false), "no record or error for a cleared selection"); + controller.dispose(); + } finally { + tableGate = null; + release(); + } + // The shared request still lands for the next selection. + const { wire } = await recordFor(pngFile("next.png", [tEXt("prompt", PROMPT)])); + assert.equal(wire.resolution.state, "resolved"); +}); + test("a PNG File becomes the server-shaped wire with local provenance", async () => { const file = pngFile("Fox Render.PNG", [tEXt("prompt", PROMPT), tEXt("workflow", WORKFLOW)]); const { wire, record, handle } = await recordFor(file); @@ -66,8 +107,12 @@ test("a PNG File becomes the server-shaped wire with local provenance", async () size: file.size, width: 640, height: 480, modified_time: 1_700_000_000.123 }); assert.equal(wire.success, true); assert.equal(wire.inspection_version, 1); - assert.deepEqual(wire.prompts, { positive: { status: "unresolved" }, negative: { status: "unresolved" } }); - assert.deepEqual(wire.resolution, { state: "unresolved", sampler_id: null, reason: "Resolved in this browser from the workflow.", reason_code: null, node: null }); + // The roles the server's inspector resolves for the same records (local-resolver.mjs). + assert.deepEqual(wire.prompts, { + positive: { status: "resolved", text: "a red fox in snow, detailed fur", source: "graph-inferred" }, + negative: { status: "resolved", text: "blurry, lowres", source: "graph-inferred" }, + }); + assert.deepEqual(wire.resolution, { state: "resolved", sampler_id: "3", reason: "", reason_code: null, node: null }); assert.deepEqual(wire.library, { status: "unavailable", scope: "saved-library", tags: [], category_scope: null, tags_scope: null }); assert.equal(wire.metadata.status, "available"); assert.deepEqual(wire.metadata.raw, { prompt: PROMPT, workflow: WORKFLOW }); @@ -96,6 +141,33 @@ test("a PNG File becomes the server-shaped wire with local provenance", async () assert.equal(exported.file.source_label, "Selected local file"); }); +test("roles answer as the server's inspector: unreadable, unavailable table, ambiguous", async () => { + const png = { media: "image", kind: "png" }; + const unreadable = m.buildLocalPayload({ read: null, file: { name: "a.png" }, classification: png }); + assert.deepEqual(unreadable.resolution, { state: "unresolved", sampler_id: null, reason: "Media metadata could not be read", reason_code: null, node: null }); + assert.equal(unreadable.prompts.positive.message, "Metadata in this file could not be read."); + const records = { prompt: PROMPT }; + const read = { status: "complete", records, limited: [], width: 2, height: 3 }; + // Without a table (it could not be fetched) the roles stay open, with the server's own line. + const missing = m.buildLocalPayload({ read, file: { name: "a.png" }, classification: png }); + assert.equal(missing.resolution.reason, "Inspection node semantics are unavailable"); + assert.equal(missing.prompts.positive.message, "The inspector's node table is unavailable."); + const semantics = await (await import("../../web/js/workspace/local-semantics.mjs")).loadInspectionSemantics(); + const graph = JSON.parse(PROMPT); + graph["9"] = { ...graph["3"], inputs: { ...graph["3"].inputs, positive: ["8", 0] } }; + graph["8"] = { class_type: "CLIPTextEncode", inputs: { text: "a cat", clip: ["4", 1] } }; + const several = m.buildLocalPayload({ read: { ...read, records: { prompt: JSON.stringify(graph) } }, file: { name: "a.png" }, classification: png, semantics }); + assert.equal(several.resolution.reason, "Multiple sampler branches"); + assert.deepEqual(several.prompts.positive, { status: "ambiguous", text: null, source: null }); + // The legacy fill then applies exactly as it does to the server's answer for the same bytes in Images. + const handle = await handleFor(pngFile("grid.png", [tEXt("prompt", JSON.stringify(graph))])); + const local = m.localFileAdapter.toRecord(several, handle, extractGenerationFacts); + const asServed = { ...several, file: { ...several.file, observation: "current-file", source_label: "output" } }; + const served = projectInspectionPayload(asServed, { kind: "rooted-file", key: "0:grid.png", root_index: 0, path: "grid.png", root_scope: null }, null, extractGenerationFacts); + assert.deepEqual(local.prompts, served.prompts); + assert.deepEqual(local.generation, served.generation); +}); + test("file facts follow the server: extension like Path.suffix, null when unknown", async () => { const cases = [["a.b.PnG", ".png"], [".hidden", ""], ["noext", ""], ["dot.", ""], ["x.tar.gz", ".gz"]]; for (const [name, extension] of cases) { @@ -307,3 +379,89 @@ test("the parity corpus PNGs read into renderable records", async () => { assert.ok(["parsed", "limited", "malformed"].includes(wire.metadata.prompt_graph.status)); } }); + +// M4: resolution runs on the page's main thread, so a read yields between its bounded steps (the busy state paints +// and input is handled) and no step may exceed a budget on the largest record the readers keep (2 MiB of roles). +const ROLE_BYTES = 2 * 1024 * 1024; +// Generous for a shared CI runner: a desktop resolves these in 130-455 ms. +const STEP_BUDGET_MS = 2500; +const ENCODE = (text) => ({ class_type: "CLIPTextEncode", inputs: { text, clip: ["4", 1] } }); +const KSAMPLER = (positive, negative, latent) => ({ class_type: "KSampler", inputs: { seed: 1, steps: 20, cfg: 8.0, sampler_name: "euler", scheduler: "normal", + denoise: 1.0, model: ["4", 0], positive, negative, latent_image: latent } }); +const LOADERS = { "4": { class_type: "CheckpointLoaderSimple", inputs: { ckpt_name: "m.safetensors" } }, "5": { class_type: "EmptyLatentImage", inputs: { width: 64, height: 64, batch_size: 1 } } }; +/** The largest graph of this shape whose JSON fits the role budget. */ +function maximal(build, high) { + let low = 1; + while (low < high) { + const middle = (low + high + 1) >> 1; + if (Buffer.byteLength(JSON.stringify(build(middle)), "utf8") <= ROLE_BYTES) low = middle; + else high = middle - 1; + } + return JSON.stringify(build(low)); +} +const MAXIMAL_GRAPHS = { + // Many candidates: every sampler is a final stage with its own pair. + independent: maximal((count) => { + const graph = { ...LOADERS }; + for (let index = 0; index < count; index++) { + graph[`s${index}`] = KSAMPLER([`p${index}`, 0], [`n${index}`, 0], ["5", 0]); + graph[`p${index}`] = ENCODE(`fox ${index}`); + graph[`n${index}`] = ENCODE(`blur ${index}`); + } + return graph; + }, 6666), + // One long stage chain through the latent: the deepest stage walk. + chain: maximal((count) => { + const graph = { ...LOADERS, "6": ENCODE("fox"), "7": ENCODE("blur") }; + for (let index = 0; index < count; index++) graph[`s${index}`] = KSAMPLER(["6", 0], ["7", 0], index ? [`s${index - 1}`, 0] : ["5", 0]); + return graph; + }, 19996), +}; + +test("resolution of a maximal 2 MiB graph stays within the step budget", async () => { + const { resolveLocalEvidence } = await import("../../web/js/workspace/local-resolver.mjs"); + const semantics = await (await import("../../web/js/workspace/local-semantics.mjs")).loadInspectionSemantics(); + for (const [name, prompt] of Object.entries(MAXIMAL_GRAPHS)) { + assert.ok(Buffer.byteLength(prompt, "utf8") > ROLE_BYTES - 1024, `${name} fills the role budget`); + const started = performance.now(); + const evidence = resolveLocalEvidence({ prompt }, semantics); + const elapsed = performance.now() - started; + assert.ok(elapsed < STEP_BUDGET_MS, `${name}: ${Math.round(elapsed)} ms`); + assert.notEqual(evidence.resolution.reason_code, "malformed", name); + } +}); + +test("a read yields between bounded steps and answers byte for byte as one synchronous build", async () => { + const semantics = await (await import("../../web/js/workspace/local-semantics.mjs")).loadInspectionSemantics(); + const file = pngFile("maximal.png", [tEXt("prompt", MAXIMAL_GRAPHS.independent)]); + const handle = await handleFor(file); + const marks = []; + const yieldControl = async (signal) => { + signal?.throwIfAborted(); + marks.push(performance.now()); + await new Promise((resolve) => setTimeout(resolve, 0)); + }; + const started = performance.now(); + const wire = await m.localFileAdapter.read(handle, { signal: new AbortController().signal, yieldControl }); + marks.push(performance.now()); + // Resolution and the projection each run in a turn of their own after the table is in. + assert.ok(marks.length >= 3, `yields: ${marks.length - 1}`); + const gaps = marks.map((mark, index) => mark - (index ? marks[index - 1] : started)); + assert.ok(Math.max(...gaps) < STEP_BUDGET_MS, `longest step ${Math.round(Math.max(...gaps))} ms`); + const { result } = await m.readLocalFile(file, { classification: handle.classification }); + const direct = await m.fitLocalPayload(m.buildLocalPayload({ read: result, file: { name: handle.filename, size: file.size, lastModified: file.lastModified }, + classification: handle.classification, semantics })); + assert.equal(JSON.stringify(wire), JSON.stringify(direct)); + assert.equal(wire.resolution.state, "ambiguous"); + // An abort at any yield ends the read there. + for (let stop = 0; stop < marks.length - 1; stop++) { + const controller = new AbortController(); + let seen = 0; + const stopping = async (signal) => { + if (seen++ === stop) controller.abort(); + signal.throwIfAborted(); + await new Promise((resolve) => setTimeout(resolve, 0)); + }; + await assert.rejects(m.localFileAdapter.read(handle, { signal: controller.signal, yieldControl: stopping }), { name: "AbortError" }, `yield ${stop}`); + } +}); diff --git a/tests/js/workspace-local-resolver.test.js b/tests/js/workspace-local-resolver.test.js new file mode 100644 index 0000000..cc9e160 --- /dev/null +++ b/tests/js/workspace-local-resolver.test.js @@ -0,0 +1,161 @@ +// PR L3 Tasks 8-9: the server's inspection resolver in this browser. The values below are what CPython answers +// (json.loads, len, str.strip, repr, utils/prompt_inspector.inspect_prompt_evidence); the full comparison with the +// server runs in tests/test_local_inspect_parity.py through tests/js/support/local-inspect-oracle.mjs. +import test from 'node:test'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; + +const py = await import('../../web/js/workspace/py-json.mjs'); +const resolver = await import('../../web/js/workspace/local-resolver.mjs'); +const semantics = resolver.compileSemantics(JSON.parse(fs.readFileSync(new URL('../../web/js/inspection-semantics.json', import.meta.url), 'utf8'))); + +test('json.loads keeps Python value kinds and dict order', () => { + const value = py.pyJsonLoads('{"9": 1, "10": 1.0, "a": NaN, "9": [true, -0, 9007199254740993, -Infinity]}'); + assert.ok(value instanceof Map); + // A repeated key keeps its first position and takes its last value; integer-like keys keep text order. + assert.deepEqual([...value.keys()], ['9', '10', 'a']); + const [flag, zero, big, negative] = value.get('9'); + assert.equal(flag, true); assert.equal(zero, 0); assert.equal(big, 9007199254740993n); + assert.ok(negative instanceof py.PyFloat); assert.equal(negative.value, -Infinity); + assert.ok(value.get('10') instanceof py.PyFloat, '1.0 is a float, not an int'); + assert.ok(Number.isNaN(value.get('a').value)); + assert.equal(py.isInt(value.get('10')), false); + assert.equal(py.pyJsonLoads('"\\ud83d\\ude00\\ud800"'), '\u{1f600}\ud800'); + for (const bad of ['{}', '{"a":1,}', '[01]', '{"a" 1}', '"\u0001"', '"\\x"', '1 2', '-', `${'9'.repeat(4301)}`, '"\\ud800\\uzzzz"']) { + assert.throws(() => py.pyJsonLoads(bad), py.PyValueError, bad); + } + assert.equal(py.pyJsonLoads(` ${'9'.repeat(4300)}\n`), BigInt('9'.repeat(4300))); +}); + +// One depth cap for both browser CPython-JSON parsers (py-json.mjs here, local-video.mjs for video envelopes): every +// array or object counts, an empty one too, as CPython's scanner enters recursion for each; past the cap it refuses. +test('json.loads refuses nesting past the shared depth cap, counting every container', () => { + const video = import('../../web/js/workspace/local-video.mjs'); + assert.equal(py.JSON_MAX_DEPTH, 1000); + const nest = (depth, inner = '') => '['.repeat(depth) + inner + ']'.repeat(depth); + const objects = (depth, inner) => '{"a":'.repeat(depth) + inner + '}'.repeat(depth); + for (const text of [nest(1000), nest(1000, '1'), nest(999, '{}'), objects(1000, '1'), objects(999, '[]')]) assert.doesNotThrow(() => py.pyJsonLoads(text)); + for (const text of [nest(1001), nest(1001, '1'), nest(1000, '{}'), objects(1001, '1'), objects(1000, '[]')]) { + assert.throws(() => py.pyJsonLoads(text), py.PyValueError); + } + return video.then(({ pythonJsonLoads, PythonJsonError }) => { + for (const text of [nest(1000), nest(1000, '1'), objects(999, '[]')]) assert.doesNotThrow(() => pythonJsonLoads(text)); + for (const text of [nest(1001), nest(1001, '1'), objects(1000, '[]')]) { + assert.throws(() => pythonJsonLoads(text), error => error instanceof PythonJsonError && error.recursion === true); + } + }); +}); + +test('str helpers measure, slice and strip as CPython', () => { + assert.equal(py.pyLen('a\u{1f600}\ud800'), 3); + assert.equal(py.pySlice('\u{1f600}\u{1f600}x', 2), '\u{1f600}\u{1f600}'); + // str.isspace() includes \x1c-\x1f and \x85 and excludes , unlike String.prototype.trim. + assert.equal(py.pyStrip('\x1c\x85 a b \x1f'), 'a b'); + assert.equal(py.pyStrip('a'), 'a'); + assert.deepEqual([1.0, 0.0001, 1e-5, 1e16, 123456789012345.6, -2.5, 1e22].map(py.pyFloatRepr), + ['1.0', '0.0001', '1e-05', '1e+16', '123456789012345.6', '-2.5', '1e+22']); + assert.deepEqual([null, true, 0, 1n, new py.PyFloat(2), '', [], new Map()].map(py.pyTruthy), [false, true, false, true, true, false, false, false]); + assert.deepEqual([1, 1n, true, new py.PyFloat(1), '1', 2].map(py.pyEqualsOne), [true, true, true, true, false, false]); +}); + +const encode = text => ({class_type: 'CLIPTextEncode', inputs: {text, clip: ['4', 1]}}); +const sampler = (extra = {}) => ({class_type: 'KSampler', inputs: {seed: 1, positive: ['6', 0], negative: ['7', 0], latent_image: ['5', 0], model: ['4', 0], ...extra}}); +const base = (nodes = {}) => ({'3': sampler(), '4': {class_type: 'CheckpointLoaderSimple', inputs: {ckpt_name: 'm.safetensors'}}, + '5': {class_type: 'EmptyLatentImage', inputs: {width: 64, height: 64, batch_size: 1}}, '6': encode('a fox'), '7': encode('blurry'), ...nodes}); + +test('a single chain resolves both roles with their sources', () => { + const evidence = resolver.resolveLocalEvidence({prompt: JSON.stringify(base())}, semantics); + assert.deepEqual(evidence, { + prompts: {positive: {status: 'resolved', text: 'a fox', source: 'graph-inferred'}, negative: {status: 'resolved', text: 'blurry', source: 'graph-inferred'}}, + resolution: {state: 'resolved', sampler_id: '3', reason: '', reason_code: null, node: null}, + }); +}); + +test('records without roles, malformed text and a missing sampler answer as the server', () => { + assert.deepEqual(resolver.resolveLocalEvidence({workflow: '{}'}, semantics).resolution, + {state: 'absent', sampler_id: null, reason: 'No parsed prompt metadata', reason_code: null, node: null}); + const malformed = resolver.resolveLocalEvidence({prompt: '{broken'}, semantics); + assert.equal(malformed.resolution.reason, 'Prompt evidence is malformed'); + assert.equal(malformed.prompts.positive.message, 'Prompt metadata in this file is malformed.'); + const none = resolver.resolveLocalEvidence({prompt: JSON.stringify({'1': encode('x'), '2': {class_type: 'MySampler', inputs: {positive: ['1', 0]}}})}, semantics); + assert.deepEqual(none.resolution, {state: 'unresolved', sampler_id: null, reason: 'No supported sampler pair found (saw MySampler)', reason_code: 'no-sampler', node: null}); + assert.equal(none.prompts.negative.message, 'No supported sampler was found.'); + assert.equal(resolver.resolveLocalEvidence({prompt: JSON.stringify(base()), parameters: 'x'}, null).resolution.reason, 'Inspection node semantics are unavailable'); +}); + +test('a float output slot is not a link, and a runtime node is named', () => { + const floatSlot = resolver.resolveLocalEvidence({prompt: JSON.stringify(base()).replace('"positive":["6",0]', '"positive":["6",0.0]')}, semantics); + assert.deepEqual(floatSlot.resolution, {state: 'unresolved', sampler_id: '3', reason: 'Expected a typed graph link or text input', reason_code: 'malformed', node: null}); + const runtime = resolver.resolveLocalEvidence({prompt: JSON.stringify(base({'6': {class_type: 'PromptSearchList', inputs: {}}}))}, semantics); + assert.deepEqual(runtime.resolution.node, {id: '6', class_type: 'PromptSearchList'}); + assert.equal(runtime.prompts.positive.message, 'Prompt is chosen at run time (PromptSearchList).'); +}); + +test('execution evidence replaces a PromptManagerPair text when it matches the node inputs', () => { + const pair = {class_type: 'PromptManagerPair', inputs: {text: 'fox', negative_text: 'blur', prepend_text: '', append_text: ''}}; + const record = {text: 'fox', negative_text: 'blur', positive_text: 'fox, executed', negative_effective_text: 'blur', prepend_text: '', append_text: ''}; + const graph = base({'3': sampler({positive: ['8', 0], negative: ['8', 1]}), '8': pair}); + const evidence = resolver.resolveLocalEvidence({prompt: JSON.stringify(graph), comfyassets_prompt_pairs: JSON.stringify({version: 1, nodes: {'8': {records: [record]}}})}, semantics); + assert.deepEqual(evidence.prompts.positive, {status: 'resolved', text: 'fox, executed', source: 'execution'}); + const stale = resolver.resolveLocalEvidence({prompt: JSON.stringify(graph), comfyassets_prompt_pairs: JSON.stringify({version: 1, nodes: {'8': {records: [{...record, text: 'other'}]}}})}, semantics); + assert.equal(stale.resolution.reason, 'Execution evidence does not match recorded node inputs'); +}); + +test('identical sampler branches resolve to their shared pair, differing ones stay ambiguous (#270)', () => { + const shared = resolver.resolveLocalEvidence({prompt: JSON.stringify(base({'9': sampler()}))}, semantics); + assert.deepEqual(shared.resolution, {state: 'resolved', sampler_id: null, reason: 'Every sampler branch uses the same prompt pair', reason_code: null, node: null}); + assert.equal(shared.prompts.positive.text, 'a fox'); + const differ = resolver.resolveLocalEvidence({prompt: JSON.stringify(base({'9': sampler({positive: ['8', 0]}), '8': encode('a cat')}))}, semantics); + assert.deepEqual(differ.resolution, {state: 'ambiguous', sampler_id: null, reason: 'Multiple sampler branches', reason_code: null, node: null}); + assert.equal(differ.prompts.positive.status, 'ambiguous'); +}); + +test('a detailer stage is compared with the sampler in its image ancestry', () => { + const graph = base({'10': {class_type: 'VAEDecode', inputs: {samples: ['3', 0]}}, '8': encode('a cat'), '12': {class_type: 'SaveImage', inputs: {images: ['11', 0]}}, + '11': {class_type: 'FaceDetailer', inputs: {image: ['10', 0], model: ['4', 0], positive: ['8', 0], negative: ['7', 0]}}}); + const evidence = resolver.resolveLocalEvidence({prompt: JSON.stringify(graph)}, semantics); + assert.deepEqual(evidence.resolution, {state: 'ambiguous', sampler_id: '11', reason: 'Sampler stages have different prompts', reason_code: 'multistage-differs', node: null}); + assert.equal(evidence.prompts.positive.message, undefined); +}); + +test('A1111 parameters split on the unique settings footer as Python does', () => { + const read = text => resolver.resolveLocalEvidence({parameters: text}, semantics); + assert.deepEqual(read('a fox\nNegative prompt: blur\nSteps: 20, Sampler: euler').prompts, { + positive: {status: 'resolved', text: 'a fox', source: 'embedded-parameters'}, negative: {status: 'resolved', text: 'blur', source: 'embedded-parameters'}, + }); + // Python's multiline ^ and $ break only at \n: a U+2028 or a lone \r never starts the footer line. + for (const text of ['a fox\u2028Steps: 20, x', 'a fox\rSteps: 20, x']) assert.equal(read(text).resolution.reason, 'A1111 settings footer is not unique'); + // \d is any Unicode decimal digit and \s spans line breaks, as in Python's re. + assert.equal(read('a fox\nSteps: \u0662\u0660, x').resolution.reason, 'Negative prompt delimiter is absent'); + assert.equal(read('a fox\nSteps:\n 20 \n, x').resolution.state, 'absent'); + assert.equal(read('a fox\nSteps: 1, x\nNegative Template: n\nTemplate: t').resolution.reason_code, 'malformed'); + assert.equal(read('\u{1f600}'.repeat(60000) + '\nSteps: 1, x').resolution.state, 'absent', 'the length limit counts code points'); +}); + +test('an unusable semantics table is refused', () => { + for (const doc of [null, {schema: 2}, {schema: 1, samplers: []}]) assert.throws(() => resolver.compileSemantics(doc), resolver.SemanticsError); +}); + +// The committed server answers (tests/fixtures/local-inspect/resolver-vectors.json, written by +// `python3 -m tests.local_resolver_cases --write` and checked current by the Python suite). +test('committed server answers equal the local evidence', () => { + const {vectors} = JSON.parse(fs.readFileSync(new URL('../fixtures/local-inspect/resolver-vectors.json', import.meta.url), 'utf8')); + const canonical = value => Array.isArray(value) ? value.map(canonical) : + value !== null && typeof value === 'object' ? Object.fromEntries(Object.keys(value).sort().map(key => [key, canonical(value[key])])) : value; + let compared = 0; + for (const {name, records, evidence} of vectors) { + assert.deepEqual(canonical(resolver.resolveLocalEvidence(records, semantics)), canonical(evidence), name); + compared++; + } + assert.ok(compared > 280, `compared ${compared}`); +}); + +test('a list or object workflow node type is skipped, as on the server (#286)', () => { + const graph = base({'6': {class_type: 'PromptManager', inputs: {text: 'a fox', clip: ['4', 1]}}}); + for (const type of [['PromptManager'], {name: 'PromptManager'}]) { + const evidence = resolver.resolveLocalEvidence({prompt: JSON.stringify(graph), workflow: JSON.stringify({nodes: [{id: 6, type, widgets_values: ['x']}]})}, semantics); + assert.equal(evidence.resolution.state, 'resolved'); + assert.equal(evidence.prompts.positive.status, 'resolved'); + assert.equal(evidence.prompts.positive.text, 'a fox'); + } +}); diff --git a/tests/js/workspace-local-semantics.test.js b/tests/js/workspace-local-semantics.test.js new file mode 100644 index 0000000..f0e657d --- /dev/null +++ b/tests/js/workspace-local-semantics.test.js @@ -0,0 +1,43 @@ +// web/js/workspace/local-semantics.mjs (#249 local Inspect, PR L3 Task 10): the node table local Inspect resolves +// with is the server's own web/js/inspection-semantics.json, fetched once through the API client before a file is +// chosen. A table that cannot be fetched or used answers as the server does when its table is unusable. +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; + +const TABLE = fs.readFileSync(new URL("../../web/js/inspection-semantics.json", import.meta.url), "utf8"); +let instance = 0; +/** A fresh module instance (its cache is per page) with `fetch` and the API client stubbed. */ +async function load(respond) { + const calls = []; + globalThis.window = { ApiClient: { resolveUrl: (path) => `/proxy${path}` } }; + globalThis.fetch = async (url, init) => { calls.push([url, init]); return respond(); }; + const module = await import(`../../web/js/workspace/local-semantics.mjs?instance=${++instance}`); + return { module, calls }; +} +test.after(() => { delete globalThis.window; delete globalThis.fetch; }); + +test("the table is fetched once through the API client and compiled", async () => { + const { module, calls } = await load(() => new Response(TABLE, { status: 200 })); + const [first, second] = await Promise.all([module.loadInspectionSemantics(), module.loadInspectionSemantics()]); + assert.equal(first, second); + assert.ok(first.samplers.has("KSampler")); + assert.equal(await module.loadInspectionSemantics(), first); + assert.deepEqual(calls, [["/proxy/prompt_manager/js/inspection-semantics.json", { credentials: "same-origin" }]]); +}); + +test("a failed or unusable table is null, and a later selection asks again", async () => { + for (const respond of [() => new Response("nope", { status: 404 }), () => new Response("{\"schema\": 2}", { status: 200 }), () => { throw new TypeError("offline"); }]) { + const { module, calls } = await load(respond); + assert.equal(await module.loadInspectionSemantics(), null); + assert.equal(await module.loadInspectionSemantics(), null); + assert.equal(calls.length, 2); + } +}); + +test("without the API client nothing is fetched", async () => { + const { module, calls } = await load(() => new Response(TABLE)); + delete globalThis.window; + assert.equal(await module.loadInspectionSemantics(), null); + assert.deepEqual(calls, []); +}); diff --git a/tests/js/workspace-local-session.test.js b/tests/js/workspace-local-session.test.js index 7749876..36bd64d 100644 --- a/tests/js/workspace-local-session.test.js +++ b/tests/js/workspace-local-session.test.js @@ -193,8 +193,8 @@ test("unclassified input creates no object URL", async () => { // declares a supported type it opens the inspector's unreadable state, with no preview and no URL (ledger ruling). const gone = pngFile("gone.png", "fox", { gate: () => Promise.reject(new DOMException("The file was removed", "NotReadableError")) }); assert.equal(value.select([gone]), "accepted"); - await settle(); - const unreadable = value.controller.state; + // The read yields between its steps (local-inspection.mjs): wait for the answer, not a fixed number of turns. + const unreadable = await recorded(value.controller); assert.ok(unreadable.record, "the unreadable record is published"); assert.deepEqual([value.state.phase, value.state.message, value.state.preview], ["ready", m.LOCAL_SESSION_MESSAGES.unreadable, null]); assert.equal(m.LOCAL_SESSION_MESSAGES.unreadable, "Embedded metadata could not be read."); diff --git a/tests/js/workspace-toolbar.test.js b/tests/js/workspace-toolbar.test.js index d825d6a..91e1c3b 100644 --- a/tests/js/workspace-toolbar.test.js +++ b/tests/js/workspace-toolbar.test.js @@ -521,6 +521,10 @@ test('copy fallback selects the text', async () => { assert.equal(note.className, 'small'); assert.equal(note.textContent, 'Automatic clipboard access requires a secure browser context.'); assert.throws(() => openCopyFallback(42, { scope }), TypeError); + // LI-4 (D117): the settings summary names its own dialog; the select-to-copy body is the same. + openCopyFallback('Seed: 7', { scope, title: 'Copy settings summary' }); + assert.equal(byId(dom, 'modal-title').textContent, 'Copy settings summary'); + assert.equal(byId(dom, 'copy-text').value, 'Seed: 7'); } finally { closeWorkspaceDialog(); scope.dispose(); diff --git a/tests/local_resolver_cases.py b/tests/local_resolver_cases.py new file mode 100644 index 0000000..3880ef4 --- /dev/null +++ b/tests/local_resolver_cases.py @@ -0,0 +1,1405 @@ +"""Record sets for the local resolver parity test (#249 local Inspect, PR L3 Task 8). + +Every case is a dict of record texts as ``read_inspection_file`` returns them +(``prompt``, ``workflow``, ``comfyassets_prompt_pairs``), so the server's +``inspect_prompt_evidence`` and the browser's ``resolveLocalEvidence`` read the +same bytes. ``golden_cases`` names one case per traced strategy, bound and +malformed shape; ``fuzz_cases`` builds coherent single-sampler graphs from the +same node vocabulary, then corrupts some of them. All content is synthetic. +``single_chain`` says, from the server's own sampler table, whether a record +set resolves without candidate selection (the Task 8 subset); +``local_resolver_selection_cases`` holds the candidate-selection cases. +""" + +import argparse +import json +import random +from pathlib import Path + +from utils.inspection_semantics import get_semantics +from utils.prompt_inspector import inspect_prompt_evidence +from utils.prompt_pair_resolver import INSPECTION_PROFILE + +VECTORS_PATH = ( + Path(__file__).resolve().parent + / "fixtures" + / "local-inspect" + / "resolver-vectors.json" +) +# Committed record sets stay small; the large bound cases are built at test time. +MAX_VECTOR_CHARS = 20_000 +COMMITTED_FUZZ = (0, 60) + +SPACES = ["", " ", "\t", "\n", "\x1c", "\x85", " ", "", "
 "] +WORDS = ["fox", "snow", "café", "猫", "\U0001f600", "a,", "detailed fur", ""] + + +def _dump(graph, ensure_ascii=False): + return json.dumps(graph, ensure_ascii=ensure_ascii) + + +def _encode(text, name="CLIPTextEncode"): + return {"class_type": name, "inputs": {"text": text, "clip": ["4", 1]}} + + +def _graph(positive, negative, extra=None, sampler=None): + graph = { + "3": sampler + or { + "class_type": "KSampler", + "inputs": { + "seed": 1, + "model": ["4", 0], + "positive": positive, + "negative": negative, + "latent_image": ["5", 0], + }, + }, + "4": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "m"}}, + "5": {"class_type": "EmptyLatentImage", "inputs": {"width": 64}}, + } + graph.update(extra or {}) + return graph + + +def _pair(text="fox", negative="blur", prepend="", append=""): + return { + "class_type": "PromptManagerPair", + "inputs": { + "text": text, + "negative_text": negative, + "prepend_text": prepend, + "append_text": append, + }, + } + + +def _execution(node_id, **changes): + record = { + "text": "fox", + "negative_text": "blur", + "positive_text": "fox executed", + "negative_effective_text": "blur", + "prepend_text": "", + "append_text": "", + } + record.update(changes) + return json.dumps({"version": 1, "nodes": {node_id: {"records": [record]}}}) + + +def _chain(length, start="6"): + nodes = {start: _encode("deep")} + previous = start + for index in range(length): + node_id = f"r{index}" + nodes[node_id] = {"class_type": "Reroute", "inputs": {"value": [previous, 0]}} + previous = node_id + return nodes, previous + + +def _combine_tree(levels): + """A full ConditioningCombine tree over equal encoders: many distinct visits.""" + nodes, layer = {}, [] + for index in range(2**levels): + nodes[f"e{index}"] = _encode("same") + layer.append(f"e{index}") + level = 0 + while len(layer) > 1: + nxt = [] + for index in range(0, len(layer), 2): + node_id = f"c{level}_{index}" + nodes[node_id] = { + "class_type": "ConditioningCombine", + "inputs": { + "conditioning_1": [layer[index], 0], + "conditioning_2": [layer[index + 1], 0], + }, + } + nxt.append(node_id) + layer, level = nxt, level + 1 + return nodes, layer[0] + + +def golden_cases(): + """Named record sets, one per strategy, bound and malformed shape.""" + cases = {} + + def add(name, graph=None, prompt=None, **records): + cases[name] = {"prompt": prompt if prompt is not None else _dump(graph)} + cases[name].update(records) + + neg = ["7", 0] + base = {"6": _encode("a fox"), "7": _encode("blurry")} + add("encode", _graph(["6", 0], neg, base)) + add("empty-positive", _graph(["6", 0], neg, {**base, "6": _encode(" \x85")})) + add("feff-positive", _graph(["6", 0], neg, {**base, "6": _encode("")})) + add("no-negative", _graph(["6", 0], None, base)) + add( + "negative-missing-input", + None, + prompt=_dump(_graph(["6", 0], neg, base)).replace('"negative": ["7", 0], ', ""), + ) + add( + "float-slot", + None, + prompt=_dump(_graph(["6", 0], neg, base)).replace('["6", 0]', '["6", 0.0]'), + ) + add( + "bool-slot", + None, + prompt=_dump(_graph(["6", 0], neg, base)).replace('["6", 0]', '["6", true]'), + ) + add("int-id", None, prompt=_dump(_graph([6, 0], neg, base))) + add("dangling", _graph(["60", 0], neg, base)) + add("wrong-slot", _graph(["6", 3], neg, base)) + add( + "cycle", + _graph( + ["8", 0], + neg, + {**base, "8": {"class_type": "Reroute", "inputs": {"value": ["8", 0]}}}, + ), + ) + add( + "reroute-ambiguous", + _graph( + ["8", 0], + neg, + { + **base, + "8": { + "class_type": "Reroute", + "inputs": {"value": ["6", 0], "in": ["6", 0]}, + }, + }, + ), + ) + add( + "duplicate-key", + None, + prompt=_dump(_graph(["6", 0], neg, base))[:-1] + + ', "6": ' + + _dump(_encode("last wins")) + + "}", + ) + add( + "nan-input", + None, + prompt=_dump(_graph(["6", 0], neg, base)).replace('"seed": 1', '"seed": NaN'), + ) + add( + "class-type-number", + _graph( + ["6", 0], neg, {**base, "6": {"class_type": 1.5, "inputs": {"text": "x"}}} + ), + ) + add( + "class-type-missing", + _graph(["6", 0], neg, {**base, "6": {"inputs": {"text": "x"}}}), + ) + add( + "inputs-list", + _graph( + ["6", 0], + neg, + {**base, "6": {"class_type": "CLIPTextEncode", "inputs": ["x"]}}, + ), + ) + add("prompt-list", None, prompt="[1, 2]") + add("prompt-empty", None, prompt="{}") + add("prompt-bom", None, prompt="" + _dump(_graph(["6", 0], neg, base))) + add( + "huge-int", + None, + prompt=_dump(_graph(["6", 0], neg, base)).replace( + '"seed": 1', '"seed": ' + "9" * 4301 + ), + ) + add("only-execution", None, prompt=None) + cases["only-execution"] = {"comfyassets_prompt_pairs": _execution("8")} + add( + "no-sampler", + { + "1": _encode("x"), + "2": {"class_type": "XSampler", "inputs": {"positive": ["1", 0]}}, + "9": {"class_type": "YGuider", "inputs": {"guider": ["1", 0]}}, + }, + ) + add("no-sampler-plain", {"1": _encode("x")}) + sdxl = { + "class_type": "CLIPTextEncodeSDXL", + "inputs": {"text_g": "a", "text_l": "a"}, + } + add("sdxl-equal", _graph(["8", 0], neg, {**base, "8": sdxl})) + add( + "sdxl-one", + _graph( + ["8", 0], + neg, + { + **base, + "8": { + "class_type": "CLIPTextEncodeSDXL", + "inputs": {"text_g": "a", "text_l": ""}, + }, + }, + ), + ) + add( + "sdxl-differ", + _graph( + ["8", 0], + neg, + { + **base, + "8": { + "class_type": "CLIPTextEncodeSDXL", + "inputs": {"text_g": "a", "text_l": "b"}, + }, + }, + ), + ) + for flag in (False, True, 1, ["9", 0]): + smz = { + "class_type": "smZ CLIPTextEncode", + "inputs": {"text": "t", "text_g": "g", "text_l": "g", "with_SDXL": flag}, + } + add(f"smz-{json.dumps(flag)}", _graph(["8", 0], neg, {**base, "8": smz})) + add( + "zeroed", + _graph( + ["6", 0], + ["8", 0], + { + **base, + "8": { + "class_type": "ConditioningZeroOut", + "inputs": {"conditioning": ["6", 0]}, + }, + }, + ), + ) + add( + "passthrough", + _graph( + ["8", 0], + neg, + { + **base, + "8": { + "class_type": "FluxGuidance", + "inputs": {"conditioning": ["6", 0], "guidance": 3.5}, + }, + }, + ), + ) + add( + "controlnet-slot1", + _graph( + ["8", 0], + ["8", 1], + { + **base, + "8": { + "class_type": "ControlNetApplyAdvanced", + "inputs": {"positive": ["6", 0], "negative": ["7", 0]}, + }, + }, + ), + ) + add( + "combine-equal", + _graph( + ["8", 0], + neg, + { + **base, + "9": _encode("a fox"), + "8": { + "class_type": "ConditioningCombine", + "inputs": {"conditioning_1": ["6", 0], "conditioning_2": ["9", 0]}, + }, + }, + ), + ) + add( + "combine-differ", + _graph( + ["8", 0], + neg, + { + **base, + "8": { + "class_type": "ConditioningCombine", + "inputs": {"conditioning_1": ["6", 0], "conditioning_2": ["7", 0]}, + }, + }, + ), + ) + for condition in (True, False, ["9", 0], 1, "true"): + select = { + "class_type": "easy ifElse", + "inputs": {"boolean": condition, "on_true": ["6", 0], "on_false": ["7", 0]}, + } + add( + f"select-{json.dumps(condition)}", + _graph( + ["8", 0], + ["10", 0], + { + **base, + "8": select, + "10": _encode("neg"), + "9": {"class_type": "PrimitiveBoolean", "inputs": {"value": True}}, + }, + ), + ) + same = { + "class_type": "easy ifElse", + "inputs": {"boolean": ["9", 0], "on_true": ["6", 0], "on_false": ["11", 0]}, + } + add( + "select-converge", + _graph(["8", 0], neg, {**base, "8": same, "11": _encode("a fox")}), + ) + # Two selectors on one condition: forced together, so two candidates, not four. + add( + "select-shared", + _graph( + ["8", 0], + ["12", 0], + { + **base, + "8": { + "class_type": "easy ifElse", + "inputs": { + "boolean": ["9", 0], + "on_true": ["6", 0], + "on_false": ["7", 0], + }, + }, + "12": { + "class_type": "Switch conditioning [Crystools]", + "inputs": { + "boolean": ["9", 0], + "on_true": ["7", 0], + "on_false": ["6", 0], + }, + }, + }, + ), + ) + add( + "runtime", + _graph( + ["8", 0], + neg, + {**base, "8": {"class_type": "PromptSearchList", "inputs": {}}}, + ), + ) + add( + "unknown-encoder", + _graph( + ["8", 0], + neg, + { + **base, + "8": {"class_type": "FancyEncoder" + "x" * 80, "inputs": {"text": "x"}}, + }, + ), + ) + add( + "primitive", + _graph( + ["6", 0], + neg, + { + **base, + "6": _encode(["8", 0]), + "8": { + "class_type": "PrimitiveStringMultiline", + "inputs": {"value": " multi\nline "}, + }, + }, + ), + ) + add( + "string-kind-mismatch", + _graph( + ["8", 0], + neg, + {**base, "8": {"class_type": "PrimitiveString", "inputs": {"value": "x"}}}, + ), + ) + concat = { + "class_type": "StringConcatenate", + "inputs": {"string_a": " a ", "string_b": "", "delimiter": ", "}, + } + add( + "string-concatenate", + _graph(["6", 0], neg, {**base, "6": _encode(["8", 0]), "8": concat}), + ) + for clean in ("true", "False", True, "TRUE", 0): + text_concat = { + "class_type": "Text Concatenate", + "inputs": { + "text_b": " b ", + "text_a": " a", + "text_aa": "x", + "text_c": "", + "clean_whitespace": clean, + }, + } + add( + f"text-concatenate-{json.dumps(clean)}", + _graph(["6", 0], neg, {**base, "6": _encode(["8", 0]), "8": text_concat}), + ) + for strip in (True, False, 1): + multiline = { + "class_type": "StringConstantMultiline", + "inputs": {"string": "\n a\nb \n", "strip_newlines": strip}, + } + add( + f"strip-newlines-{json.dumps(strip)}", + _graph(["6", 0], neg, {**base, "6": _encode(["8", 0]), "8": multiline}), + ) + for count, as_list in ( + (3, False), + (1, False), + (0, False), + (1001, False), + (2, True), + (2.0, False), + (True, False), + ): + join = { + "class_type": "JoinStringMulti", + "inputs": { + "string_1": "", + "string_2": "b", + "string_3": "", + "string_4": "d", + "inputcount": count, + "delimiter": " | ", + "return_list": as_list, + }, + } + add( + f"join-multi-{json.dumps(count)}-{json.dumps(as_list)}", + _graph(["6", 0], neg, {**base, "6": _encode(["8", 0]), "8": join}), + ) + manager = { + "class_type": "PromptManager", + "inputs": { + "text": "main", + "prepend_text": " before ", + "append_text": "", + "clip": ["4", 1], + }, + } + add("prompt-manager", _graph(["8", 0], neg, {**base, "8": manager})) + add( + "prompt-manager-null-prepend", + _graph( + ["8", 0], + neg, + { + **base, + "8": {**manager, "inputs": {**manager["inputs"], "prepend_text": None}}, + }, + ), + ) + for name, slot in ( + ("PromptManagerV2", 0), + ("PromptManagerV2", 1), + ("PromptManagerPositive", 0), + ("PromptManagerNegative", 0), + ): + historical = { + "class_type": name, + "inputs": { + "text": " main ", + "negative_text": " neg ", + "prepend_text": "lead,", + "append_text": None, + }, + } + add( + f"historical-{name}-{slot}", + _graph(["8", slot], neg, {**base, "8": historical}), + ) + pair_graph = _graph(["8", 0], ["8", 1], {**base, "8": _pair()}) + add("pair-graph", pair_graph) + add("pair-execution", pair_graph, comfyassets_prompt_pairs=_execution("8")) + add( + "pair-execution-other-node", + pair_graph, + comfyassets_prompt_pairs=_execution("99"), + ) + add( + "pair-execution-mismatch", + pair_graph, + comfyassets_prompt_pairs=_execution("8", text="other"), + ) + add( + "pair-execution-negative-changed", + pair_graph, + comfyassets_prompt_pairs=_execution("8", negative_effective_text="x"), + ) + add( + "pair-execution-version-true", + pair_graph, + comfyassets_prompt_pairs=_execution("8").replace( + '"version": 1', '"version": true' + ), + ) + add( + "pair-execution-version-float", + pair_graph, + comfyassets_prompt_pairs=_execution("8").replace( + '"version": 1', '"version": 1.0' + ), + ) + add( + "pair-execution-truncated", + pair_graph, + comfyassets_prompt_pairs=_execution("8").replace( + '"version": 1', '"version": 1, "truncated": []' + ), + ) + add("pair-execution-bad-json", pair_graph, comfyassets_prompt_pairs="{nope") + two = json.loads(_execution("8")) + two["nodes"]["8"]["records"].append( + dict(two["nodes"]["8"]["records"][0], positive_text="other") + ) + add( + "pair-execution-two-records", + pair_graph, + comfyassets_prompt_pairs=json.dumps(two), + ) + linked_pair = _graph( + ["8", 0], + ["8", 1], + { + **base, + "8": {**_pair(), "inputs": {**_pair()["inputs"], "text": ["9", 0]}}, + "9": {"class_type": "PromptSearchList", "inputs": {}}, + }, + ) + add( + "pair-execution-runtime-input", + linked_pair, + comfyassets_prompt_pairs=_execution("8"), + ) + add( + "pair-execution-runtime-wrong-slot", + _graph( + ["8", 0], + ["8", 1], + { + **base, + "8": {**_pair(), "inputs": {**_pair()["inputs"], "text": ["9", 2]}}, + "9": {"class_type": "PromptManagerText", "inputs": {"text": "x"}}, + }, + ), + comfyassets_prompt_pairs=_execution("8"), + ) + guided = { + "class_type": "SamplerCustomAdvanced", + "inputs": { + "noise": ["20", 0], + "guider": ["21", 0], + "sampler": ["22", 0], + "sigmas": ["23", 0], + "latent_image": ["5", 0], + }, + } + add( + "custom-cfg", + _graph( + None, + None, + { + **base, + "21": { + "class_type": "CFGGuider", + "inputs": { + "positive": ["6", 0], + "negative": ["7", 0], + "model": ["4", 0], + "cfg": 5, + }, + }, + }, + sampler=guided, + ), + ) + add( + "custom-basic", + _graph( + None, + None, + { + **base, + "21": { + "class_type": "BasicGuider", + "inputs": {"conditioning": ["6", 0], "model": ["4", 0]}, + }, + }, + sampler=guided, + ), + ) + add( + "custom-reroute-guider", + _graph( + None, + None, + { + **base, + "21": {"class_type": "Reroute", "inputs": {"value": ["24", 0]}}, + "24": { + "class_type": "BasicGuider", + "inputs": {"conditioning": ["6", 0]}, + }, + }, + sampler=guided, + ), + ) + add( + "custom-unknown-guider", + _graph( + None, + None, + { + **base, + "21": {"class_type": "DualCFGGuider", "inputs": {"cond1": ["6", 0]}}, + }, + sampler=guided, + ), + ) + add( + "latent-stage", + _graph( + ["6", 0], + neg, + { + **base, + "5": {"class_type": "LatentUpscale", "inputs": {"samples": ["30", 0]}}, + "30": { + "class_type": "KSamplerPreview", + "inputs": {"model": ["4", 0], "positive": ["6", 0]}, + }, + }, + ), + ) + add( + "latent-encode", + _graph( + ["6", 0], + neg, + { + **base, + "5": { + "class_type": "VAEEncode", + "inputs": {"pixels": ["31", 0], "vae": ["4", 2]}, + }, + "31": {"class_type": "LoadImage", "inputs": {"image": "x.png"}}, + }, + ), + ) + add( + "latent-cycle", + _graph( + ["6", 0], + neg, + { + **base, + "5": {"class_type": "LatentUpscale", "inputs": {"samples": ["3", 0]}}, + }, + ), + ) + for override in ("", "wild", ["6", 0]): + detail = { + "class_type": "KSampler", + "inputs": { + "positive": ["6", 0], + "negative": neg, + "latent_image": ["5", 0], + "wildcard": override, + }, + } + add( + f"override-ignored-{json.dumps(override)}", + _graph(None, None, base, sampler=detail), + ) + chain, end = _chain(70) + add("depth-limit", _graph([end, 0], neg, {**base, **chain})) + chain, end = _chain(61) + add("depth-near", _graph([end, 0], neg, {**base, **chain})) + tree, top = _combine_tree(11) + add("work-limit-visits", _graph([top, 0], neg, {**base, **tree})) + tree, top = _combine_tree(9) + add("diamond-memo", _graph([top, 0], [top, 0], {**base, **tree})) + add("text-limit", _graph(["6", 0], neg, {**base, "6": _encode("x" * 100_001)})) + add( + "text-at-limit", + _graph(["6", 0], neg, {**base, "6": _encode("\U0001f600" * 100_000)}), + ) + big = { + f"s{index}": { + "class_type": "PrimitiveString", + "inputs": {"value": "y" * 99_000}, + } + for index in range(20) + } + joined = { + "class_type": "JoinStringMulti", + "inputs": { + "string_1": ["s0", 0], + "inputcount": 20, + "delimiter": "", + "return_list": False, + }, + } + joined["inputs"].update( + {f"string_{index + 1}": [f"s{index}", 0] for index in range(1, 20)} + ) + add( + "join-over-length", + _graph(["6", 0], neg, {**base, **big, "6": _encode(["8", 0]), "8": joined}), + ) + concats = { + f"k{index}": { + "class_type": "StringConcatenate", + "inputs": {"string_a": "z" * 90_000, "string_b": "", "delimiter": ""}, + } + for index in range(20) + } + combine = {f"q{index}": _encode([f"k{index}", 0]) for index in range(20)} + add("built-chars", _graph(["q0", 0], ["q1", 0], {**base, **concats, **combine})) + ceiling = { + str(index): {"class_type": "Note", "inputs": {}} for index in range(100, 20_102) + } + add("graph-ceiling", _graph(["6", 0], neg, {**base, **ceiling})) + workflow = { + "nodes": [ + {"id": 6, "type": "PromptManager", "widgets_values": ["own text"]}, + {"id": 7, "type": "PromptManager", "widgets_values": ["other text"]}, + ] + } + overwritten = {**base, "6": _encode("shared"), "7": _encode("shared")} + overwritten["6"]["inputs"]["search_text"] = "" + add( + "overwritten", + _graph(["6", 0], ["7", 0], overwritten), + workflow=json.dumps(workflow), + ) + nested = { + "nodes": [{"id": 1, "type": "sub-a", "widgets_values": []}], + "definitions": { + "subgraphs": [ + { + "id": "sub-a", + "nodes": [ + { + "id": 6, + "type": "PromptManagerFocused", + "widgets_values": {"text": "a"}, + }, + { + "id": 7, + "type": "PromptManagerFocused", + "widgets_values": ["b"], + }, + ], + } + ] + }, + } + nested_graph = { + **base, + "1:6": { + "class_type": "PromptManager", + "inputs": {"text": "same", "clip": ["4", 1]}, + }, + "1:7": {"class_type": "PromptManager", "inputs": {"text": "same"}}, + } + add( + "overwritten-subgraph", + _graph(["1:6", 0], ["1:7", 0], nested_graph), + workflow=json.dumps(nested), + ) + add( + "overwritten-bad-workflow", + _graph(["6", 0], ["7", 0], overwritten), + workflow="{bad", + ) + # A list or object node ``type`` is skipped like a non-dict node (#286), also + # inside a subgraph; a skipped node never hides the rest of the walk. + for label, kind in (("list", ["PromptManager"]), ("dict", {"a": 1})): + add( + f"workflow-type-{label}", + _graph(["6", 0], ["7", 0], overwritten), + workflow=json.dumps( + {"nodes": [{"id": 6, "type": "PromptManager"}, {"id": 8, "type": kind}]} + ), + ) + add( + "workflow-type-in-subgraph", + _graph(["1:6", 0], ["1:7", 0], nested_graph), + workflow=json.dumps( + { + **nested, + "definitions": { + "subgraphs": [{"id": "sub-a", "nodes": [{"id": 2, "type": [1]}]}] + }, + } + ), + ) + add( + "workflow-type-skipped-keeps-overwritten", + _graph(["6", 0], ["7", 0], overwritten), + workflow=json.dumps( + { + "nodes": [ + workflow["nodes"][0], + {"id": 8, "type": ["PromptManager"]}, + workflow["nodes"][1], + ] + } + ), + ) + add( + "workflow-type-without-id", + _graph(["6", 0], ["7", 0], overwritten), + workflow=json.dumps({"nodes": [{"id": True, "type": ["x"]}, "skipped"]}), + ) + add( + "several-samplers", + _graph( + ["6", 0], + neg, + { + **base, + "9": { + "class_type": "KSampler", + "inputs": {"positive": ["6", 0], "negative": neg}, + }, + }, + ), + ) + add( + "detailer", + _graph( + None, + None, + base, + sampler={ + "class_type": "FaceDetailer", + "inputs": { + "image": ["5", 0], + "positive": ["6", 0], + "negative": neg, + "wildcard": "", + }, + }, + ), + ) + cases["parameters-only"] = { + "parameters": "a fox\nNegative prompt: blur\nSteps: 20, Sampler: euler" + } + cases["prompt-and-parameters"] = { + "prompt": _dump(_graph(["6", 0], neg, base)), + "parameters": "ignored", + } + return cases + + +def _visits_graph(count): + """``count`` PrimitiveString links joined under one encoder (``count`` visits).""" + first, second = count // 2, count - count // 2 + nodes = { + f"p{index}": {"class_type": "PrimitiveString", "inputs": {"value": "w"}} + for index in range(count) + } + for name, start, size in (("j1", 0, first), ("j2", first, second)): + inputs = {"inputcount": max(size, 1), "delimiter": "", "return_list": False} + inputs.update( + {f"string_{index + 1}": [f"p{start + index}", 0] for index in range(size)} + ) + inputs.setdefault("string_1", "") + nodes[name] = {"class_type": "JoinStringMulti", "inputs": inputs} + nodes["k"] = { + "class_type": "StringConcatenate", + "inputs": {"string_a": ["j1", 0], "string_b": ["j2", 0], "delimiter": ""}, + } + nodes["6"] = _encode(["k", 0]) + nodes["7"] = _encode("blurry") + return {"prompt": _dump(_graph(["6", 0], ["7", 0], nodes))} + + +def _depth_graph(length): + chain, end = _chain(length) + return { + "prompt": _dump(_graph([end, 0], ["7", 0], {**chain, "7": _encode("blurry")})) + } + + +def _scan_graph(tail): + """Whitespace-only Text Concatenate parts: scanned before stripping, never built.""" + nodes, parts = {}, [] + for index in range(4): + if index < 3: + inputs = { + f"text_{letter}": " " * 99_000 for letter in "abcdefghijklmnopqrstu" + } + else: + inputs, left = {}, tail + for letter in "abcdefghijklmnopqrstu": + inputs[f"text_{letter}"] = " " * min(99_000, left) + left -= min(99_000, left) + inputs["text_z"] = "kept" if index == 0 else "" + nodes[f"t{index}"] = {"class_type": "Text Concatenate", "inputs": inputs} + parts.append([f"t{index}", 0]) + nodes["k"] = { + "class_type": "JoinStringMulti", + "inputs": { + "string_1": parts[0], + "string_2": parts[1], + "string_3": parts[2], + "string_4": parts[3], + "inputcount": 4, + "delimiter": "", + "return_list": False, + }, + } + nodes["6"] = _encode(["k", 0]) + nodes["7"] = _encode("blurry") + return {"prompt": _dump(_graph(["6", 0], ["7", 0], nodes))} + + +def _threshold(build, low, high): + """The largest parameter in [low, high) the server still resolves.""" + + def resolved(value): + evidence = inspect_prompt_evidence( + build(value), None, profile=INSPECTION_PROFILE + ) + return evidence["resolution"]["state"] == "resolved" + + assert resolved(low) and not resolved(high) + while high - low > 1: + middle = (low + high) // 2 + if resolved(middle): + low = middle + else: + high = middle + return low + + +# The nesting the browser's CPython-JSON parsers accept (py-json.mjs JSON_MAX_DEPTH). +JSON_MAX_DEPTH = 1000 +JSON_DEPTHS = (JSON_MAX_DEPTH - 1, JSON_MAX_DEPTH, JSON_MAX_DEPTH + 1) + + +def _nested(depth): + """``depth`` nested arrays.""" + return "[" * depth + "]" * depth + + +def depth_cases(): + """``(name, kind, depth, records)``: a deep record at the JSON depth cap. + + A ``prompt`` holds a junk input nested to ``depth`` containers in all (the + graph, its node and the inputs are three); parsed, both roles resolve. + A ``workflow`` nested to ``depth`` makes two PromptManager nodes + overwritten (R1) when it is read, and the prompt resolves when it is not. + """ + cases = [] + base = {"6": _encode("a fox"), "7": _encode("blurry")} + for depth in JSON_DEPTHS: + graph = _dump(_graph(["6", 0], ["7", 0], {**base, "9": {"class_type": "Note"}})) + junk = '"inputs": {"junk": ' + _nested(depth - 3) + "}" + prompt = graph.replace('"class_type": "Note"', '"class_type": "Note", ' + junk) + cases.append((f"prompt-depth-{depth}", "prompt", depth, {"prompt": prompt})) + overwritten = {**base, "6": _encode("shared"), "7": _encode("shared")} + overwritten["6"]["inputs"]["search_text"] = "" + nodes = [ + {"id": 6, "type": "PromptManager", "widgets_values": ["own text"]}, + {"id": 7, "type": "PromptManager", "widgets_values": ["other text"]}, + ] + workflow = json.dumps({"nodes": nodes, "extra": 0}).replace( + '"extra": 0', '"extra": ' + _nested(depth - 1) + ) + records = { + "prompt": _dump(_graph(["6", 0], ["7", 0], overwritten)), + "workflow": workflow, + } + cases.append((f"workflow-depth-{depth}", "workflow", depth, records)) + return cases + + +def boundary_cases(): + """Each work bound at its edge: the last value that resolves, then the next.""" + cases = {} + for name, build, low, high in ( + ("visits", _visits_graph, 10, 2000), + ("depth", _depth_graph, 1, 80), + ("scanned", _scan_graph, 0, 2_000_000), + ): + edge = _threshold(build, low, high) + cases[f"{name}-edge"] = build(edge) + cases[f"{name}-over"] = build(edge + 1) + long_name = "\U0001f600" * 70 + cases["named-astral"] = { + "prompt": _dump( + _graph( + ["\U0001f600" * 70, 0], + ["7", 0], + { + "\U0001f600" + * 70: {"class_type": long_name, "inputs": {"text": "x"}}, + "7": _encode("b"), + }, + ) + ) + } + return cases + + +class _Builder: + """Coherent random graphs over the traced vocabulary, sometimes corrupted.""" + + def __init__(self, rng): + self.rng = rng + self.nodes = {} + self.records = {} + self.counter = 100 + + def new_id(self): + self.counter += 1 + return str(self.counter) + + def word(self): + rng = self.rng + parts = [rng.choice(SPACES), rng.choice(WORDS), rng.choice(SPACES)] + if rng.random() < 0.3: + parts.append(rng.choice(WORDS)) + return "".join(parts) + + def string(self, depth): + """A string input: a literal, or a link to a string node.""" + rng = self.rng + if depth > 3 or rng.random() < 0.45: + return self.word() + node_id, choice = self.new_id(), rng.randrange(8) + if choice == 0: + node = { + "class_type": rng.choice( + ["PrimitiveString", "PrimitiveStringMultiline"] + ), + "inputs": {"value": self.string(depth + 1)}, + } + elif choice == 1: + node = { + "class_type": "StringConcatenate", + "inputs": { + "string_a": self.string(depth + 1), + "string_b": self.string(depth + 1), + "delimiter": rng.choice(["", ", ", " "]), + }, + } + elif choice == 2: + inputs = { + f"text_{letter}": self.string(depth + 1) + for letter in rng.sample("abcd", rng.randint(1, 3)) + } + inputs["clean_whitespace"] = rng.choice(["true", "false", True]) + node = {"class_type": "Text Concatenate", "inputs": inputs} + elif choice == 3: + node = { + "class_type": "StringConstantMultiline", + "inputs": { + "string": self.string(depth + 1), + "strip_newlines": rng.choice([True, False]), + }, + } + elif choice == 4: + count = rng.randint(1, 4) + inputs = { + f"string_{index}": self.string(depth + 1) + for index in range(1, count + 1) + if index == 1 or rng.random() < 0.8 + } + inputs.update( + { + "inputcount": count, + "delimiter": rng.choice([" ", ","]), + "return_list": rng.random() < 0.1, + } + ) + node = {"class_type": "JoinStringMulti", "inputs": inputs} + elif choice == 5: + node = { + "class_type": "Reroute", + "inputs": {"value": self.string_link(depth + 1)}, + } + elif choice == 6: + node = { + "class_type": rng.choice(["StringConstant", "TextInput"]), + "inputs": {rng.choice(["string", "text"]): self.string(depth + 1)}, + } + else: + node = { + "class_type": "PromptManagerText", + "inputs": { + "text": self.string(depth + 1), + "prepend_text": self.word(), + "append_text": self.word(), + }, + } + self.nodes[node_id] = node + return [node_id, 0] + + def string_link(self, depth): + value = self.string(depth) + if isinstance(value, list): + return value + node_id = self.new_id() + self.nodes[node_id] = { + "class_type": "PrimitiveString", + "inputs": {"value": value}, + } + return [node_id, 0] + + def conditioning(self, depth): + rng = self.rng + node_id = self.new_id() + choice = rng.randrange(11) if depth < 4 else 0 + slot = 0 + if choice == 0: + node = { + "class_type": "CLIPTextEncode", + "inputs": {"text": self.string(depth + 1), "clip": ["4", 1]}, + } + elif choice == 1: + text = self.string(depth + 1) + node = { + "class_type": "CLIPTextEncodeSDXL", + "inputs": { + "text_g": text, + "text_l": ( + text if rng.random() < 0.6 else rng.choice(["", self.word()]) + ), + }, + } + elif choice == 2: + node = { + "class_type": "FluxGuidance", + "inputs": {"conditioning": self.conditioning(depth + 1)}, + } + elif choice == 3: + node = { + "class_type": "ConditioningZeroOut", + "inputs": {"conditioning": self.conditioning(depth + 1)}, + } + elif choice == 4: + first = self.conditioning(depth + 1) + node = { + "class_type": "ConditioningCombine", + "inputs": { + "conditioning_1": first, + "conditioning_2": ( + first if rng.random() < 0.5 else self.conditioning(depth + 1) + ), + }, + } + elif choice == 5: + condition = rng.choice([True, False, ["4", 0], ["4", 1]]) + node = { + "class_type": "easy ifElse", + "inputs": { + "boolean": condition, + "on_true": self.conditioning(depth + 1), + "on_false": self.conditioning(depth + 1), + }, + } + elif choice == 6: + node = { + "class_type": rng.choice(["PromptManager", "PromptManagerFocused"]), + "inputs": { + "text": self.string(depth + 1), + "prepend_text": self.word(), + "append_text": self.word(), + "clip": ["4", 1], + }, + } + elif choice == 7: + node = { + "class_type": rng.choice(["PromptManagerV2", "PromptManagerPositive"]), + "inputs": { + "text": self.string(depth + 1), + "prepend_text": self.word(), + "negative_text": self.word(), + }, + } + elif choice == 8: + slot = rng.choice([0, 1]) + texts = { + "text": self.word(), + "negative_text": self.word(), + "prepend_text": self.word(), + "append_text": self.word(), + } + node = {"class_type": "PromptManagerPair", "inputs": dict(texts)} + if rng.random() < 0.6: + record = { + **texts, + "positive_text": self.word(), + "negative_effective_text": texts["negative_text"], + } + record["prepend_text"], record["append_text"] = ( + record["prepend_text"].strip(), + record["append_text"].strip(), + ) + if rng.random() < 0.2: + record["text"] = record["text"] + "!" + self.records[EXECUTION_KEY] = json.dumps( + {"version": 1, "nodes": {node_id: {"records": [record]}}} + ) + elif choice == 9: + node = { + "class_type": "Reroute", + "inputs": {"value": self.conditioning(depth + 1)}, + } + else: + node = { + "class_type": rng.choice(["PromptSearchList", "FancyEncoder"]), + "inputs": {"text": self.word()}, + } + self.nodes[node_id] = node + return [node_id, slot] + + def corrupt(self): + rng = self.rng + node_id = rng.choice(sorted(self.nodes)) + node = self.nodes[node_id] + links = [ + key + for key, value in node.get("inputs", {}).items() + if isinstance(value, list) + ] + choice = rng.randrange(6) + if choice == 0 and links: + node["inputs"][rng.choice(links)][1] = rng.choice([0.0, True, 7, -1]) + elif choice == 1 and links: + node["inputs"][rng.choice(links)][0] = rng.choice(["missing", node_id]) + elif choice == 2: + node["class_type"] = rng.choice([None, 3, "Unknown"]) + elif choice == 3: + node["inputs"] = rng.choice([[], {}]) + elif choice == 4 and links: + del node["inputs"][rng.choice(links)] + else: + node.pop("inputs", None) + + +EXECUTION_KEY = "comfyassets_prompt_pairs" + + +def fuzz_cases(seed, count): + rng = random.Random(seed) + cases = {} + for index in range(count): + builder = _Builder(rng) + positive = builder.conditioning(0) + negative = builder.conditioning(0) if rng.random() < 0.9 else None + graph = _graph(positive, negative, builder.nodes) + if negative is None: + del graph["3"]["inputs"]["negative"] + if rng.random() < 0.25: + builder.nodes = graph + builder.corrupt() + records = {"prompt": json.dumps(graph, ensure_ascii=rng.random() < 0.5)} + records.update(builder.records) + cases[f"fuzz-{seed}-{index}"] = records + return cases + + +def single_chain(records): + """Whether the server answers ``records`` without choosing among samplers.""" + roles = {key for key in records if key in ("prompt", "parameters", EXECUTION_KEY)} + if "prompt" not in roles: + return "parameters" not in roles + try: + graph = json.loads(records["prompt"]) + except (ValueError, RecursionError): + return True + if ( + not isinstance(graph, dict) + or not graph + or len(graph) > INSPECTION_PROFILE.node_ceiling + ): + return True + samplers = get_semantics().samplers + found = [ + node["class_type"] + for node in graph.values() + if isinstance(node, dict) + and isinstance(node.get("class_type"), str) + and node["class_type"] in samplers + and samplers[node["class_type"]]["strategy"] + in ("ksampler", "custom-advanced", "detailer-stage") + ] + return len(found) <= 1 and not any( + samplers[name]["strategy"] == "detailer-stage" for name in found + ) + + +def _utf8(records): + """Whether the record texts can be written as UTF-8 (no lone surrogate).""" + try: + json.dumps(records, ensure_ascii=False).encode("utf-8") + except UnicodeEncodeError: + return False + return True + + +def committed_vectors(): + """The committed record sets with the server's evidence, in a stable order.""" + try: + from tests import local_resolver_selection_cases as selection + except ImportError: # pragma: no cover - discover -s tests puts tests/ first + import local_resolver_selection_cases as selection + + named = {**golden_cases(), **selection.selection_cases()} + cases = { + name: records + for name, records in named.items() + if len(json.dumps(records)) <= MAX_VECTOR_CHARS and _utf8(records) + } + cases.update(fuzz_cases(*COMMITTED_FUZZ)) + cases.update(selection.selection_fuzz_cases(*COMMITTED_FUZZ)) + vectors = [ + { + "name": name, + "records": records, + "evidence": inspect_prompt_evidence( + records, None, profile=INSPECTION_PROFILE + ), + } + for name, records in cases.items() + ] + return {"version": 2, "vectors": vectors} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("--write", action="store_true", help="rewrite the vectors") + if parser.parse_args().write: + text = json.dumps(committed_vectors(), ensure_ascii=False, sort_keys=True) + VECTORS_PATH.write_text(text + "\n", encoding="utf-8", newline="\n") + + +if __name__ == "__main__": + main() diff --git a/tests/local_resolver_selection_cases.py b/tests/local_resolver_selection_cases.py new file mode 100644 index 0000000..9591e97 --- /dev/null +++ b/tests/local_resolver_selection_cases.py @@ -0,0 +1,574 @@ +"""Candidate-selection record sets for the local resolver parity test (PR L3 Task 9). + +``local_resolver_cases`` covers one sampler's tracing. These cases reach the +rest of ``_resolve``: several sampler candidates and the identical-branch rule +(#270), stages that only reach previews, detailer stages and their upstream +samplers (multistage), and A1111 ``parameters`` with every footer shape. The +server's ``inspect_prompt_evidence`` is the oracle; nothing here states an +expected answer. All content is synthetic. +""" + +import json +import random + +try: + from tests.local_resolver_cases import EXECUTION_KEY, SPACES, WORDS, _Builder +except ImportError: # pragma: no cover - discover -s tests puts tests/ first + from local_resolver_cases import EXECUTION_KEY, SPACES, WORDS, _Builder + + +def _encode(text): + return {"class_type": "CLIPTextEncode", "inputs": {"text": text, "clip": ["4", 1]}} + + +def _sampler(positive, negative, latent=None, name="KSampler"): + inputs = {"seed": 1, "model": ["4", 0], "positive": positive} + if negative is not None: + inputs["negative"] = negative + inputs["latent_image"] = latent or ["5", 0] + return {"class_type": name, "inputs": inputs} + + +def _decode(sampler_id): + return {"class_type": "VAEDecode", "inputs": {"samples": [sampler_id, 0]}} + + +def _save(image, name="SaveImage"): + return {"class_type": name, "inputs": {"images": image}} + + +def _detailer(image, positive, negative, name="FaceDetailer", **extra): + inputs = {"image": image, "model": ["4", 0], "positive": positive} + inputs["negative"] = negative + inputs.update(extra) + return {"class_type": name, "inputs": inputs} + + +def _base(**nodes): + graph = { + "4": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "m"}}, + "5": {"class_type": "EmptyLatentImage", "inputs": {"width": 64}}, + "6": _encode("a fox"), + "7": _encode("blurry"), + "8": _encode("a cat"), + } + graph.update(nodes) + return graph + + +def _samplers(): + """Several unanchored samplers: identical, differing and mixed branches.""" + same = _sampler(["6", 0], ["7", 0]) + cases = { + "two-identical": _base(**{"3": same, "9": same}), + "two-differ": _base(**{"3": same, "9": _sampler(["8", 0], ["7", 0])}), + "two-negative-differs": _base(**{"3": same, "9": _sampler(["6", 0], ["8", 0])}), + "identical-without-negative": _base( + **{"3": _sampler(["6", 0], None), "9": _sampler(["6", 0], None)} + ), + "one-unresolved": _base(**{"3": same, "9": _sampler(["missing", 0], ["7", 0])}), + "both-unresolved": _base( + **{"3": _sampler(["x", 0], ["7", 0]), "9": _sampler(["y", 0], ["7", 0])} + ), + "three-identical-one-advanced": _base( + **{ + "3": same, + "9": same, + "10": _sampler(["6", 0], ["7", 0], name="KSamplerAdvanced"), + } + ), + # Equal texts, different recipes: a PromptManager pair against an encoder. + "same-text-other-recipe": _base( + **{ + "3": same, + "9": _sampler(["11", 0], ["7", 0]), + "11": { + "class_type": "PromptManager", + "inputs": { + "text": "fox", + "prepend_text": "a", + "append_text": "", + "clip": ["4", 1], + }, + }, + } + ), + "multistage-latent": _base( + **{"3": same, "9": _sampler(["6", 0], ["7", 0], latent=["3", 0])} + ), + } + selector = { + "class_type": "easy ifElse", + "inputs": {"boolean": ["4", 0], "on_true": ["6", 0], "on_false": ["8", 0]}, + } + cases["selector-and-plain"] = _base( + **{"3": same, "9": _sampler(["12", 0], ["7", 0]), "12": selector} + ) + return cases + + +def _previews(): + """Stages whose outputs reach only previews are not the saved file's.""" + same, other = _sampler(["6", 0], ["7", 0]), _sampler(["8", 0], ["7", 0]) + return { + "preview-dropped": _base( + **{ + "3": same, + "9": other, + "13": _decode("3"), + "14": _decode("9"), + "15": _save(["13", 0]), + "16": _save(["14", 0], "PreviewImage"), + } + ), + "all-previews-kept": _base( + **{ + "3": same, + "9": other, + "13": _decode("3"), + "14": _decode("9"), + "15": _save(["13", 0], "PreviewImage"), + "16": _save(["14", 0], "Image Comparer (rgthree)"), + } + ), + "preview-and-file": _base( + **{ + "3": same, + "9": other, + "13": _decode("3"), + "14": _decode("9"), + "15": _save(["13", 0]), + "16": _save(["14", 0], "PreviewImage"), + "17": _save(["14", 0]), + } + ), + "unconsumed-stage-kept": _base( + **{ + "3": same, + "9": other, + "14": _decode("9"), + "16": _save(["14", 0], "PreviewImage"), + } + ), + # A list or object class_type is never a preview class (#286). + "preview-unhashable-class": _base( + **{ + "3": same, + "9": other, + "14": _decode("9"), + "16": {"class_type": ["PreviewImage"], "inputs": {"images": ["14", 0]}}, + "17": {"class_type": {"a": 1}, "inputs": {"images": ["3", 0]}}, + } + ), + "preview-through-bad-node": _base( + **{ + "3": same, + "9": other, + "13": _decode("3"), + "15": _save(["13", 0]), + "16": _save(["9", 0], "PreviewImage"), + "18": "not a node", + "19": {"class_type": "Note", "inputs": {"x": ["18", 0]}}, + } + ), + } + + +def _detailers(): + """Detailer stages judged with the samplers in their image ancestry.""" + same = _sampler(["6", 0], ["7", 0]) + cases = { + "detailer-same-prompt": _base( + **{ + "3": same, + "10": _decode("3"), + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + "detailer-differs": _base( + **{ + "3": same, + "10": _decode("3"), + "11": _detailer(["10", 0], ["8", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + "detailer-and-own-output": _base( + **{ + "3": same, + "10": _decode("3"), + "11": _detailer(["10", 0], ["8", 0], ["7", 0]), + "12": _save(["11", 0]), + "13": _save(["10", 0]), + } + ), + "detailer-image-literal": _base( + **{ + "11": _detailer("not a link", ["6", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + "detailer-cycle": _base( + **{ + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "10": {"class_type": "ImageScale", "inputs": {"image": ["11", 0]}}, + "12": _save(["11", 0]), + } + ), + "detailer-chain": _base( + **{ + "3": same, + "10": _decode("3"), + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "21": _detailer( + ["11", 0], ["8", 0], ["7", 0], name="UltimateSDUpscale" + ), + "12": _save(["21", 0]), + } + ), + "detailer-chain-same": _base( + **{ + "3": same, + "10": _decode("3"), + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "21": _detailer(["11", 0], ["6", 0], ["7", 0], name="DetailerForEach"), + "12": _save(["21", 0]), + } + ), + "detailer-two-upstream": _base( + **{ + "3": same, + "9": _sampler(["8", 0], ["7", 0]), + "10": { + "class_type": "ImageBlend", + "inputs": {"image1": ["13", 0], "image2": ["14", 0]}, + }, + "13": _decode("3"), + "14": _decode("9"), + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + "detailer-unsupported-stage": _base( + **{ + "10": { + "class_type": "MysterySampler", + "inputs": {"positive": ["6", 0], "model": ["4", 0]}, + }, + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + "detailer-upstream-unresolved": _base( + **{ + "3": _sampler(["gone", 0], ["7", 0]), + "10": _decode("3"), + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + "detailer-upstream-selector": _base( + **{ + "3": _sampler(["15", 0], ["7", 0]), + "15": { + "class_type": "easy ifElse", + "inputs": { + "boolean": ["4", 0], + "on_true": ["6", 0], + "on_false": ["8", 0], + }, + }, + "10": _decode("3"), + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + "detailer-wildcard": _base( + **{ + "3": same, + "10": _decode("3"), + "11": _detailer(["10", 0], ["6", 0], ["7", 0], wildcard="[x|y]"), + "12": _save(["11", 0]), + } + ), + "detailer-no-upscaled-image": _base( + **{ + "3": same, + "10": _decode("3"), + "11": _detailer( + ["10", 0], ["6", 0], ["7", 0], name="UltimateSDUpscaleNoUpscale" + ), + "12": _save(["11", 0]), + } + ), + "detailer-no-sampler-upstream": _base( + **{ + "10": {"class_type": "LoadImage", "inputs": {"image": "a.png"}}, + "11": _detailer(["10", 0], ["6", 0], ["7", 0]), + "12": _save(["11", 0]), + } + ), + } + deep = {"3": _sampler(["6", 0], ["7", 0]), "d0": _decode("3")} + for index in range(1, 70): + deep[f"d{index}"] = { + "class_type": "ImageScale", + "inputs": {"image": [f"d{index - 1}", 0]}, + } + deep["11"] = _detailer(["d69", 0], ["6", 0], ["7", 0]) + deep["12"] = _save(["11", 0]) + cases["detailer-deep-ancestry"] = _base(**deep) + # More nested detailer stages than the depth bound. + stacked = {"3": _sampler(["6", 0], ["7", 0]), "s0": _decode("3")} + previous = "s0" + for index in range(1, 67): + stacked[f"s{index}"] = _detailer([previous, 0], ["6", 0], ["7", 0]) + previous = f"s{index}" + stacked["12"] = _save([previous, 0]) + cases["detailer-stacked-past-depth"] = _base(**stacked) + # Each detailer walks a wide shared image ancestry: the total visit budget + # runs out across stages before any candidate is read. + wide = { + f"l{index}": {"class_type": "LoadImage", "inputs": {}} for index in range(1500) + } + wide["hub"] = { + "class_type": "ImageBatchMany", + "inputs": {f"i{index}": [f"l{index}", 0] for index in range(1500)}, + } + for index in range(15): + wide[f"w{index}"] = _detailer(["hub", 0], ["6", 0], ["7", 0]) + wide[f"o{index}"] = _save([f"w{index}", 0]) + cases["detailers-exhaust-total-visits"] = _base(**wide) + cases["detailer-mutual-cycle"] = _base( + **{ + "11": _detailer(["21", 0], ["6", 0], ["7", 0]), + "21": _detailer(["11", 0], ["6", 0], ["7", 0]), + "12": _save(["21", 0]), + } + ) + # The sampler's output reaches a preview through more nodes than one + # detailer's allowance: the walk runs out, so the sampler is not absorbed. + long = {"3": _sampler(["6", 0], ["7", 0]), "10": _decode("3")} + previous = "10" + for index in range(2100): + long[f"c{index}"] = { + "class_type": "ImageScale", + "inputs": {"image": [previous, 0]}, + } + previous = f"c{index}" + long["p"] = _save([previous, 0], "PreviewImage") + long["11"] = _detailer(["10", 0], ["6", 0], ["7", 0]) + long["12"] = _save(["11", 0]) + cases["detailer-output-walk-exhausted"] = _base(**long) + # Every detailer's ancestry walk has its own allowance: the first one is + # wide, and the second still absorbs the first. + chained = {"3": _sampler(["6", 0], ["7", 0]), "10": _decode("3")} + chained["h1"] = { + "class_type": "ImageBatchMany", + "inputs": { + "i": ["10", 0], + **{f"i{index}": [f"a{index}", 0] for index in range(1500)}, + }, + } + chained["h2"] = { + "class_type": "ImageBatchMany", + "inputs": { + "i": ["11", 0], + **{f"i{index}": [f"b{index}", 0] for index in range(600)}, + }, + } + for index in range(1500): + chained[f"a{index}"] = {"class_type": "LoadImage", "inputs": {}} + for index in range(600): + chained[f"b{index}"] = {"class_type": "LoadImage", "inputs": {}} + chained["11"] = _detailer(["h1", 0], ["6", 0], ["7", 0]) + chained["21"] = _detailer(["h2", 0], ["6", 0], ["7", 0]) + chained["12"] = _save(["21", 0]) + cases["detailers-each-reset"] = _base(**chained) + return cases + + +_FOOTER = "Steps: 20, Sampler: euler, CFG scale: 7" + + +def _parameters(): + """A1111 ``parameters`` texts: every footer shape and delimiter rule.""" + texts = { + "basic": f"a fox\nNegative prompt: blur\n{_FOOTER}", + "no-negative": f"a fox\n{_FOOTER}", + "two-delimiters": f"a\nNegative prompt: b\nNegative prompt: c\n{_FOOTER}", + "leading-delimiter": f"Negative prompt: blur\n{_FOOTER}", + "blank-positive": f" \x85\nNegative prompt: blur\n{_FOOTER}", + "footer-not-last": f"a fox\n{_FOOTER}\nmore text", + "two-footers": f"a\n{_FOOTER}\n{_FOOTER}", + "bare-footer": "a fox\nNegative prompt: blur\nSteps: 20", + "bare-and-full": f"a fox\nSteps: 5\n{_FOOTER}", + "two-bare": "a\nSteps: 1\nSteps: 2", + "template": f"a fox\n{_FOOTER}\nTemplate: {{a|b}}", + "both-templates": f"a\n{_FOOTER}\nTemplate: x\nNegative Template: y", + "templates-reversed": f"a\n{_FOOTER}\nNegative Template: y\nTemplate: x", + "two-templates": f"a\n{_FOOTER}\nTemplate: x\nTemplate: y", + "template-multiline": f"a\n{_FOOTER}\nTemplate: x\nmore", + "crlf": f"a fox\r\nNegative prompt: blur\r\n{_FOOTER}\r\n", + "cr-only": f"a fox\rNegative prompt: blur\r{_FOOTER}", + "cr-template": f"a\n{_FOOTER}\rTemplate: x", + "line-separator": f"a fox
{_FOOTER}", + "next-line": f"a fox\x85{_FOOTER}", + "spaced-steps": "a fox\nSteps:\n 20 \n, x", + "steps-newline-bare": "a fox\nSteps:\n20\n", + "arabic-digits": "a fox\nSteps: ٢٠, Sampler: euler", + "fullwidth-digits": "a fox\nSteps: 2, x", + "no-digits": "a fox\nSteps: , x", + "trailing-spaces": f"a fox \nNegative prompt: blur \n{_FOOTER} \n \n", + "empty-negative": f"a fox\nNegative prompt:\n{_FOOTER}", + "astral-within-limit": "\U0001f600" * 60_000 + f"\n{_FOOTER}", + "over-limit": "x" * 100_001, + "at-limit": "x" * (100_000 - len(_FOOTER) - 1) + "\n" + _FOOTER, + "empty": "", + "only-footer": _FOOTER, + "lone-surrogate": f"\ud800 fox\nNegative prompt: \udfff\n{_FOOTER}", + } + cases = {f"parameters-{name}": {"parameters": text} for name, text in texts.items()} + cases["parameters-with-execution"] = { + "parameters": texts["basic"], + EXECUTION_KEY: json.dumps({"version": 1, "nodes": {}}), + } + return cases + + +def selection_cases(): + """Named record sets for every Task 9 path, each a ``read_inspection_file`` dict.""" + cases = {} + for group in (_samplers(), _previews(), _detailers()): + for name, graph in group.items(): + cases[f"select-{name}"] = {"prompt": json.dumps(graph, ensure_ascii=False)} + cases.update(_parameters()) + return cases + + +class _Selection(_Builder): + """Random graphs with several samplers, outputs, previews and detailers.""" + + def sampler(self): + rng = self.rng + positive = self.conditioning(0) + negative = self.conditioning(0) if rng.random() < 0.85 else None + name = rng.choice(["KSampler", "KSampler", "KSamplerAdvanced", "SamplerCustom"]) + node_id = self.new_id() + self.nodes[node_id] = _sampler(positive, negative, name=name) + return node_id + + def shared(self, ids): + """A copy of an earlier sampler: an identical branch.""" + node_id = self.new_id() + self.nodes[node_id] = json.loads(json.dumps(self.nodes[self.rng.choice(ids)])) + return node_id + + def output(self, image): + rng = self.rng + choice = rng.randrange(5) + if choice == 4: + return + name = ["SaveImage", "SaveImage", "PreviewImage", "PreviewAny"][choice] + self.nodes[self.new_id()] = _save(image, name) + + def detailer(self, image): + rng = self.rng + node_id = self.new_id() + positive = self.conditioning(1) if rng.random() < 0.5 else None + name = rng.choice(list(_DETAILER_NAMES)) + node = _detailer(image, positive, self.conditioning(1), name=name) + if positive is None: + node["inputs"]["positive"] = self.reuse_positive() + if name == "UltimateSDUpscaleNoUpscale": + node["inputs"]["upscaled_image"] = node["inputs"].pop("image") + if name in ("FaceDetailer", "DetailerForEach") and rng.random() < 0.15: + node["inputs"]["wildcard"] = rng.choice(["", "x", ["4", 0]]) + self.nodes[node_id] = node + return node_id + + def reuse_positive(self): + samplers = [ + node + for node in self.nodes.values() + if node.get("class_type") + in ("KSampler", "KSamplerAdvanced", "SamplerCustom") + ] + if samplers: + return self.rng.choice(samplers)["inputs"]["positive"] + return self.conditioning(1) + + def build(self): + rng = self.rng + ids = [self.sampler()] + for _ in range(rng.randrange(3)): + ids.append(self.shared(ids) if rng.random() < 0.4 else self.sampler()) + for sampler_id in list(ids): + decoded = self.new_id() + self.nodes[decoded] = _decode(sampler_id) + image = [decoded, 0] + for _ in range(rng.randrange(3)): + if rng.random() < 0.5: + image = [self.detailer(image), 0] + else: + self.output(image) + self.output(image) + if rng.random() < 0.1: + self.nodes[sampler_id]["inputs"]["latent_image"] = [rng.choice(ids), 0] + graph = { + "4": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "m"}}, + "5": {"class_type": "EmptyLatentImage", "inputs": {"width": 64}}, + } + graph.update(self.nodes) + return graph + + +_DETAILER_NAMES = ( + "FaceDetailer", + "DetailerForEach", + "UltimateSDUpscale", + "UltimateSDUpscaleNoUpscale", +) +_PARAMETER_LINES = [ + "Negative prompt:", + "Negative prompt: blur", + "Steps: 20, Sampler: euler", + "Steps: 7", + "Steps: x", + "Template: t", + "Negative Template: n", + "Steps:٣, a", +] + + +def _parameter_text(rng): + parts = [] + for _ in range(rng.randint(1, 5)): + if rng.random() < 0.5: + parts.append(rng.choice(_PARAMETER_LINES)) + else: + parts.append(rng.choice(SPACES) + rng.choice(WORDS) + rng.choice(SPACES)) + joints = ["\n", "\n", "\r\n", "\r", "
", " "] + return "".join(part + rng.choice(joints) for part in parts).rstrip( + rng.choice(["", "\n", " "]) + ) + + +def selection_fuzz_cases(seed, count): + """Seeded several-sampler graphs (sometimes corrupted) and parameters texts.""" + rng = random.Random(seed) + cases = {} + for index in range(count): + if rng.random() < 0.2: + cases[f"select-fuzz-{seed}-{index}"] = {"parameters": _parameter_text(rng)} + continue + builder = _Selection(rng) + graph = builder.build() + if rng.random() < 0.2: + builder.nodes = graph + builder.corrupt() + records = {"prompt": json.dumps(graph, ensure_ascii=rng.random() < 0.5)} + records.update(builder.records) + cases[f"select-fuzz-{seed}-{index}"] = records + return cases diff --git a/tests/test_api_core.py b/tests/test_api_core.py index 8971810..4af56a9 100644 --- a/tests/test_api_core.py +++ b/tests/test_api_core.py @@ -486,6 +486,30 @@ class TestStaticRoutes(CoreRoutesTestCase): self.assertEqual(resp.status, 200) self.assertIn("application/javascript", resp.headers["Content-Type"]) + async def test_inspection_semantics_table_is_the_one_json_served(self): + """Local Inspect reads the node table the server resolves with (#249 PR L3). + + Only that exact file is served; every other JSON stays forbidden. + """ + resp = await self.client.request( + "GET", "/prompt_manager/js/inspection-semantics.json" + ) + self.assertEqual(resp.status, 200) + self.assertIn("application/json", resp.headers["Content-Type"]) + table = Path(__file__).resolve().parents[1] / "web" / "js" + self.assertEqual( + await resp.read(), (table / "inspection-semantics.json").read_bytes() + ) + for path in ( + "js/shared/toolkit/provenance.json", + "lib/viewerjs/provenance.json", + "lib/inspection-semantics.json", + "js/workspace/..%2Finspection-semantics.json", + "js/INSPECTION-SEMANTICS.json", + ): + resp = await self.client.request("GET", f"/prompt_manager/{path}") + self.assertEqual(resp.status, 403, path) + async def test_lib_served(self): web_dir = self._fake_root() (web_dir / "lib" / "x.css").write_text("body{}") @@ -578,6 +602,28 @@ class TestStaticRoutes(CoreRoutesTestCase): resp = await self.client.request("GET", "/prompt_manager/lib/link.js") self.assertEqual(resp.status, 403) + async def test_inspection_semantics_symlink_escaping_web_dir_is_403(self): + """The exact-path JSON gets the same realpath containment as any file.""" + web_dir = self._fake_root() + secret = Path(self.tmpdir) / "secret.json" + secret.write_text('{"secret": true}') + try: + os.symlink(secret, web_dir / "js" / "inspection-semantics.json") + except (OSError, NotImplementedError): + self.skipTest("symlinks not available") + resp = await self.client.request( + "GET", "/prompt_manager/js/inspection-semantics.json" + ) + self.assertEqual(resp.status, 403) + self.assertNotIn("secret", await resp.text()) + + async def test_inspection_semantics_missing_is_404(self): + self._fake_root() + resp = await self.client.request( + "GET", "/prompt_manager/js/inspection-semantics.json" + ) + self.assertEqual(resp.status, 404) + async def test_empty_path_is_not_served(self): for prefix in ("lib", "js"): resp = await self.client.request("GET", f"/prompt_manager/{prefix}/") diff --git a/tests/test_api_prompt_inspector.py b/tests/test_api_prompt_inspector.py index 4163b43..56c0523 100644 --- a/tests/test_api_prompt_inspector.py +++ b/tests/test_api_prompt_inspector.py @@ -1643,6 +1643,62 @@ class TestPromptInspector(ImageAPITestCase): str(path), False, report_ambiguity=True ) + async def test_unhashable_workflow_node_type_is_skipped(self): + """A UI workflow node whose ``type`` is a list or dict is skipped (#286). + + The R1 check looks each node's ``type`` up among subgraph IDs; an + unhashable ``type`` used to raise there and the route answered 500. + Such a node can be neither a subgraph instance nor a PromptManager + node, so the walk skips it and a prompt that resolves still resolves. + """ + source = graph() + source["1"]["class_type"] = "PromptManager" + for kind in (["PromptManager"], {"name": "PromptManager"}): + with self.subTest(kind=type(kind).__name__): + workflow = json.dumps( + {"nodes": [{"id": 1, "type": kind, "widgets_values": ["x"]}]} + ) + png( + self.output_dir / "image.png", + prompt=json.dumps(source), + workflow=workflow, + ) + response, result = await self.inspect() + self.assertEqual(response.status, 200) + self.assertEqual(result["resolution"]["state"], "resolved") + self.assertEqual(result["resolution"]["sampler_id"], "3") + self.assertEqual(result["prompts"]["positive"]["status"], "resolved") + self.assertEqual(result["prompts"]["positive"]["text"], "portrait") + self.assertEqual(result["prompts"]["negative"]["text"], "blurry") + self.assertNotIn("unhashable", json.dumps(result)) + + async def test_unhashable_graph_class_type_is_not_a_preview_output(self): + """A list or object ``class_type`` never names a preview output (#286). + + With several samplers the inspector first drops stages that reach only + previews; looking such a ``class_type`` up among the preview classes + used to raise, and the route answered 500. + """ + for kind in (["PreviewImage"], {"name": "PreviewImage"}): + with self.subTest(kind=type(kind).__name__): + source = graph() + source["9"] = { + "class_type": "KSampler", + "inputs": {"positive": ["8", 0], "negative": ["2", 0]}, + } + source["8"] = { + "class_type": "CLIPTextEncode", + "inputs": {"text": "cat"}, + } + source["10"] = {"class_type": kind, "inputs": {"images": ["9", 0]}} + png(self.output_dir / "image.png", prompt=json.dumps(source)) + response, result = await self.inspect() + self.assertEqual(response.status, 200) + self.assertEqual( + result["resolution"]["reason"], "Multiple sampler branches" + ) + self.assertEqual(result["resolution"]["state"], "ambiguous") + class TestInspectorImageTags(ImageAPITestCase): """B3: the inspector envelope's ``image_tags`` facet (spec amendment S1).""" diff --git a/tests/test_local_inspect_parity.py b/tests/test_local_inspect_parity.py index 9fdfdd9..04d4ad5 100644 --- a/tests/test_local_inspect_parity.py +++ b/tests/test_local_inspect_parity.py @@ -51,12 +51,19 @@ from utils.prompt_inspector import ( read_inspection_file, ) +from utils.prompt_inspector import inspect_prompt_evidence, unreadable_evidence +from utils.prompt_pair_resolver import INSPECTION_PROFILE + try: from tests import inspection_parity as parity + from tests import local_resolver_cases as resolver_cases + from tests import local_resolver_selection_cases as selection_cases from tests.open_handles import assert_closed from tests.test_utils_video_metadata import HAVE_FFMPEG, write_video except ImportError: # pragma: no cover - discover -s tests puts tests/ first import inspection_parity as parity + import local_resolver_cases as resolver_cases + import local_resolver_selection_cases as selection_cases from open_handles import assert_closed from test_utils_video_metadata import HAVE_FFMPEG, write_video @@ -1111,5 +1118,306 @@ class LocalProjectionParityTests(unittest.TestCase): self.assertTrue({"parsed", "malformed", "limited"} <= seen) +def _server_evidence(records): + return inspect_prompt_evidence(records, None, profile=INSPECTION_PROFILE) + + +class LocalResolverParityTests(unittest.TestCase): + """``resolveLocalEvidence`` answers as ``inspect_prompt_evidence`` (L3 Tasks 8-9). + + Python is the oracle: every expected value is the server's own answer on the + same record texts. Task 8 ported one sampler's tracing; Task 9 ports + candidate selection (several samplers, the identical-branch rule of #270, + preview-only stages, detailer stages) and A1111 ``parameters``, so no + record set is left to the server any more. + """ + + def setUp(self): + temporary = tempfile.TemporaryDirectory() + self.addCleanup(temporary.cleanup) + self.addCleanup(assert_closed, self, temporary.name) + self.directory = Path(temporary.name) + + def _compare(self, cases): + """Assert each record set's local evidence equal; return the server answers.""" + observed = _run_oracle( + self, + [ + {"name": name, "mode": "resolve", "records": records} + for name, records in cases.items() + ], + ) + answers = {} + for name, records in cases.items(): + with self.subTest(case=name): + local = observed[name] + server = _server_evidence(records) + answers[name] = server + self.assertEqual( + _canonical_bytes(local["evidence"]), _canonical_bytes(server) + ) + return answers + + def test_local_roles_match_execution_and_single_chain_vectors(self): + files = {} + for name in parity.COMMITTED: + files[name] = parity.fixture_path(name) + for name in parity.TEST_TIME: + path = parity.fixture_path(name, self.directory) + parity.write_png(path, parity.build(name)) + files[name] = path + observed = _run_oracle( + self, + [ + {"name": name, "mode": "resolve", "path": str(path)} + for name, path in files.items() + ], + ) + vectors = { + vector["fixture"]: vector + for vector in json.loads(parity.VECTORS_PATH.read_text(encoding="utf-8")) + if vector["profile"] == "inspection" + } + compared = 0 + for name, path in files.items(): + with self.subTest(fixture=name): + local = observed[name] + try: + records = read_inspection_file(path).metadata + except MetadataReadError: + self.assertTrue(local["unreadable"]) + continue + # The single-chain subset (Task 8); the rest is Task 9's test below. + if not resolver_cases.single_chain(records): + continue + server = _server_evidence(records) + self.assertEqual( + _canonical_bytes(local["evidence"]), _canonical_bytes(server) + ) + # The committed vector agrees with the server read here. + expect = vectors[name]["expect"] + self.assertEqual(server["resolution"]["state"], expect["state"]) + self.assertEqual( + server["resolution"]["reason_code"], expect["reason_code"] + ) + compared += 1 + self.assertGreaterEqual(compared, 20) + + def test_local_roles_match_inspection_vectors(self): + """Every inspection vector: local prompts, resolution and facts equal Images'. + + The facts are ``extractGenerationFacts`` (with the legacy fill) on the + local payload, against the facts the committed vectors pin for the + server's response on the same file. + """ + vectors = [ + vector + for vector in json.loads(parity.VECTORS_PATH.read_text(encoding="utf-8")) + if vector["profile"] == "inspection" + ] + files = {} + for vector in vectors: + name = vector["fixture"] + if name in parity.TEST_TIME: + path = parity.fixture_path(name, self.directory) + parity.write_png(path, parity.build(name)) + else: + path = parity.fixture_path(name) + files[name] = path + observed = _run_oracle( + self, + [ + {"name": name, "mode": "resolve", "path": str(path)} + for name, path in files.items() + ], + ) + for vector in vectors: + name = vector["fixture"] + with self.subTest(fixture=name): + local, expect = observed[name], vector["expect"] + try: + server = _server_evidence( + read_inspection_file(files[name]).metadata + ) + except MetadataReadError: + server = unreadable_evidence() + self.assertTrue(local["unreadable"]) + self.assertEqual( + _canonical_bytes(local["evidence"]), _canonical_bytes(server) + ) + resolution, prompts = ( + local["evidence"]["resolution"], + local["evidence"]["prompts"], + ) + self.assertEqual( + ( + resolution["state"], + resolution["reason"], + resolution["reason_code"], + ), + (expect["state"], expect["reason"], expect["reason_code"]), + ) + self.assertEqual( + [ + parity._role_text( + prompts[role]["status"], prompts[role]["text"] + ) + for role in ("positive", "negative") + ], + [expect["positive"], expect["negative"]], + ) + self.assertEqual(local["facts"], expect["facts"]) + self.assertEqual(len(vectors), 28) + + def test_local_roles_match_selection_record_sets(self): + answers = self._compare(selection_cases.selection_cases()) + reasons = {answer["resolution"]["reason"] for answer in answers.values()} + self.assertTrue( + { + "Every sampler branch uses the same prompt pair", + "Multiple sampler branches", + "Sampler stages have different prompts", + "Cyclic sampler stage ancestry", + "Expected an image link", + "Unsupported sampler stage ancestry", + "Resolution depth limit reached", + "A1111 settings footer is not unique", + "Multiple negative prompt delimiters", + "Negative prompt delimiter is absent", + "Parameters exceed the length limit", + "No A1111 parameters", + } + <= reasons + ) + # A stage reaching only previews is dropped: one sampler is named. + self.assertEqual( + answers["select-preview-dropped"]["resolution"]["sampler_id"], "3" + ) + + def test_local_roles_match_fuzzed_selection_sets(self): + cases = {} + for seed in range(4): + cases.update(selection_cases.selection_fuzz_cases(seed, 150)) + answers = self._compare(cases) + reasons = [answer["resolution"]["reason"] for answer in answers.values()] + self.assertGreater(reasons.count("Multiple sampler branches"), 20) + self.assertGreater(reasons.count("Sampler stages have different prompts"), 0) + self.assertGreater( + reasons.count("Every sampler branch uses the same prompt pair"), 0 + ) + self.assertGreater(reasons.count("A1111 settings footer is not unique"), 0) + + def test_local_roles_match_golden_record_sets(self): + answers = self._compare(resolver_cases.golden_cases()) + codes = {answer["resolution"]["reason_code"] for answer in answers.values()} + self.assertTrue( + { + "malformed", + "unsupported-node", + "runtime-value", + "composite", + "work-limit", + "depth-limit", + "text-limit", + "graph-ceiling", + "no-sampler", + None, + } + <= codes + ) + sources = { + side["source"] + for answer in answers.values() + for side in answer["prompts"].values() + } + self.assertTrue( + {"execution", "graph-inferred", "zeroed-conditioning"} <= sources + ) + + def test_committed_resolver_vectors_are_current(self): + """The Node unit test's committed answers are still the server's.""" + committed = json.loads(resolver_cases.VECTORS_PATH.read_text(encoding="utf-8")) + self.assertEqual( + committed, + json.loads(json.dumps(resolver_cases.committed_vectors())), + "regenerate with: python3 -m tests.local_resolver_cases --write", + ) + + def test_local_roles_match_at_every_work_bound(self): + answers = self._compare(resolver_cases.boundary_cases()) + for name in ("visits", "depth", "scanned"): + self.assertEqual(answers[f"{name}-edge"]["resolution"]["state"], "resolved") + self.assertIn( + answers[f"{name}-over"]["resolution"]["reason_code"], + ("work-limit", "depth-limit"), + ) + self.assertEqual( + answers["named-astral"]["resolution"]["node"]["class_type"], + "\U0001f600" * 64, + ) + + def test_local_json_depth_cap_at_its_boundary(self): + """Both kinds of deep record at the browser's JSON depth cap (1,000). + + Locally a record nested past the cap is invalid JSON: a prompt is + malformed and a workflow is ignored, as the server answers when + ``json.loads`` raises RecursionError. The server's own limit depends on + the Python (TESTING.md, "Deep JSON"): about 990 on 3.10 and 3.11, so it + agrees past the cap there; about 10,000 on 3.12 and 3.13 and over + 50,000 on 3.14, so it agrees up to the cap there and reads deeper. + """ + cases = resolver_cases.depth_cases() + observed = _run_oracle( + self, + [ + {"name": name, "mode": "resolve", "records": records} + for name, _kind, _depth, records in cases + ], + ) + newer = sys.version_info >= (3, 12) + compared = 0 + for name, kind, depth, records in cases: + with self.subTest(case=name): + local = observed[name]["evidence"]["resolution"] + within = depth <= resolver_cases.JSON_MAX_DEPTH + if kind == "prompt": + expected = ( + ("resolved", None) if within else ("unresolved", "malformed") + ) + else: + # A workflow that is read finds the overwritten pair (R1). + expected = ( + ("unresolved", "malformed") if within else ("resolved", None) + ) + self.assertEqual((local["state"], local["reason_code"]), expected) + server = _server_evidence(records) + if server["resolution"]["state"] == local["state"]: + self.assertEqual( + _canonical_bytes(observed[name]["evidence"]), + _canonical_bytes(server), + ) + compared += 1 + else: + # The documented divergence only: an older server refuses + # a little below the cap, a newer one reads past it. + self.assertEqual(within, not newer) + self.assertGreaterEqual(compared, 2) + + def test_local_roles_match_fuzzed_record_sets(self): + cases = {} + for seed in range(4): + cases.update(resolver_cases.fuzz_cases(seed, 150)) + answers = self._compare(cases) + states = [answer["resolution"]["state"] for answer in answers.values()] + # Coherent graphs reach real results, not only early refusals. + self.assertGreater(states.count("resolved"), len(states) // 5) + self.assertGreater(states.count("ambiguous"), 0) + self.assertGreater(states.count("unresolved"), len(states) // 10) + self.assertGreaterEqual( + len({answer["resolution"]["reason_code"] for answer in answers.values()}), + 5, + ) + + if __name__ == "__main__": unittest.main() diff --git a/tools/vendor/frontend-coverage-baseline.json b/tools/vendor/frontend-coverage-baseline.json index bf11d2f..7d82941 100644 --- a/tools/vendor/frontend-coverage-baseline.json +++ b/tools/vendor/frontend-coverage-baseline.json @@ -181,7 +181,7 @@ }, "workspace/file-inspector.mjs": { "lines": 96, - "branches": 92, + "branches": 93, "functions": 92, "statements": 96 }, @@ -341,12 +341,42 @@ "functions": 98, "statements": 98 }, + "workspace/local-parameters.mjs": { + "lines": 98, + "branches": 94, + "functions": 98, + "statements": 98 + }, "workspace/local-projection.mjs": { "lines": 97, "branches": 96, "functions": 98, "statements": 97 }, + "workspace/local-resolver-stages.mjs": { + "lines": 94, + "branches": 93, + "functions": 98, + "statements": 94 + }, + "workspace/local-resolver-support.mjs": { + "lines": 96, + "branches": 80, + "functions": 98, + "statements": 96 + }, + "workspace/local-resolver.mjs": { + "lines": 96, + "branches": 86, + "functions": 98, + "statements": 96 + }, + "workspace/local-semantics.mjs": { + "lines": 98, + "branches": 98, + "functions": 98, + "statements": 98 + }, "workspace/local-session.mjs": { "lines": 98, "branches": 92, @@ -389,6 +419,12 @@ "functions": 98, "statements": 98 }, + "workspace/py-json.mjs": { + "lines": 97, + "branches": 92, + "functions": 98, + "statements": 97 + }, "workspace/recorded-run.mjs": { "lines": 95, "branches": 83, diff --git a/utils/prompt_inspector.py b/utils/prompt_inspector.py index 9c1bb08..e7ab375 100644 --- a/utils/prompt_inspector.py +++ b/utils/prompt_inspector.py @@ -20,6 +20,7 @@ from .prompt_pair_resolver import ( _FOOTER, EMPTY_POSITIVE_REASON, INSPECTION_PROFILE, + MALFORMED_EVIDENCE_REASON, ResolverProfile, resolve_prompt_pair, ) @@ -548,7 +549,7 @@ def inspect_prompt_evidence( resolution = { "state": "unresolved", "sampler_id": None, - "reason": "Prompt evidence is malformed", + "reason": MALFORMED_EVIDENCE_REASON, "reason_code": "malformed", "node": None, } diff --git a/utils/prompt_pair_resolver.py b/utils/prompt_pair_resolver.py index f64fee9..c6e229d 100644 --- a/utils/prompt_pair_resolver.py +++ b/utils/prompt_pair_resolver.py @@ -1237,10 +1237,13 @@ class _GraphResolver: def non_file_outputs(self) -> set: names = self.semantics.non_file_outputs + # Only a string names a class: a list or object is never looked up (#286). return { node_id for node_id, node in self.graph.items() - if isinstance(node, dict) and node.get("class_type") in names + if isinstance(node, dict) + and isinstance(node.get("class_type"), str) + and node["class_type"] in names } def producers_of(self, starts: list, previews: set) -> set: @@ -1832,6 +1835,8 @@ def _shared_pair(candidates: list) -> Optional[Dict[str, Any]]: # Bounds for walking a UI workflow's subgraph instances (R1 only). _MAX_SUBGRAPH_DEPTH = 8 +# The inspector's own line for evidence it cannot read (``inspect_prompt_evidence``). +MALFORMED_EVIDENCE_REASON = "Prompt evidence is malformed" _MAX_WORKFLOW_NODES = 100_000 @@ -1862,7 +1867,9 @@ def _prompt_manager_widgets(workflow: Any) -> Dict[str, str]: Nodes inside a subgraph run as ``":"`` API IDs (nested instances chain their IDs); a definition without an instance runs nothing. - The walk is bounded in depth and in nodes visited. + The walk is bounded in depth and in nodes visited. A node whose ``type`` is + a list or an object is skipped: it is neither a subgraph instance nor a + PromptManager node (#286). """ nodes = workflow.get("nodes") if isinstance(workflow, dict) else None if not isinstance(nodes, list): @@ -1882,6 +1889,9 @@ def _prompt_manager_widgets(workflow: Any) -> Dict[str, str]: if not isinstance(node_id, (str, int)) or isinstance(node_id, bool): continue api_id = f"{prefix}{node_id}" + if isinstance(kind, (list, dict)): + # JSON's unhashable values are never a node type (#286). + continue if kind in subgraphs and depth < _MAX_SUBGRAPH_DEPTH: stack.append((subgraphs[kind], api_id + ":", depth + 1)) continue diff --git a/web/js/workspace/file-inspector.mjs b/web/js/workspace/file-inspector.mjs index 11309cb..2d7a032 100644 --- a/web/js/workspace/file-inspector.mjs +++ b/web/js/workspace/file-inspector.mjs @@ -5,6 +5,7 @@ import { createSendButton } from './prompt-sender.mjs'; import { createWorkspaceIcon } from './icons.mjs'; import { navigateTo } from './state.mjs'; import { showWorkspaceToast } from './toast.mjs'; +import { openCopyFallback } from './workspace-dialogs.mjs'; const RAW_KEYS = ['prompt', 'workflow', 'parameters', 'comfyassets_prompt_pairs']; const RAW_LIMIT = 'Raw metadata exceeds the response limit. Download the original file to inspect it externally.'; @@ -26,6 +27,26 @@ const REVEAL_BUSY = 'The folder is already opening.'; const REVEAL_FAILED = 'The folder could not be opened. Try again.'; const FACTS = [['seed', 'Seed'], ['steps', 'Steps'], ['cfg', 'CFG'], ['sampler', 'Sampler'], ['scheduler', 'Scheduler'], ['model', 'Model']]; +// D117 (LI-4): the legacy metadata page's COPY ALL (web/metadata.html copyAllData), its lines and placeholders. +const SUMMARY_LINES = [['Checkpoint', 'model'], ['Positive Prompt', 'positive'], ['Negative Prompt', 'negative'], ['Steps', 'steps'], + ['CFG Scale', 'cfg'], ['Sampler', 'sampler'], ['Seed', 'seed']]; +const SUMMARY_MISSING = {positive:'No prompt found', negative:'No negative prompt found'}; + +/** + * The one-click settings summary (D117): the legacy COPY ALL text for what this inspector shows. A confirmed prompt + * and a known fact are copied verbatim; anything else, an explicitly empty prompt included, takes the legacy page's + * placeholder, as its parse does (`hasValue` treats '' as absent). + */ +export function settingsSummary(record) { + const roles = promptRoles(record?.prompts); + const value = key => { + if (Object.hasOwn(SUMMARY_MISSING, key)) return roles[key] ? roles[key] : SUMMARY_MISSING[key]; + const fact = record?.generation?.[key]; + return fact?.status === 'known' && typeof fact.value === 'string' && fact.value !== '' ? fact.value : 'Unknown'; + }; + return SUMMARY_LINES.map(([label, key]) => `${label}: ${value(key)}`).join('\n'); +} + function safeFilename(value) { return String(value || 'file').replace(/[\\/\x00-\x1f\x7f<>:"|?*]/g, '_').replace(/^\.+|[. ]+$/g, '') || 'file'; } @@ -175,7 +196,7 @@ function prefixedChip(prefix, text) { * `variant: 'full'` (the viewer's `#viewer-details`, imageDetails(i, true)) leaves out the cover and adds "File & * provenance" and "Workflow & raw metadata" with the downloads. `inline: true` means `panel`; neither means `full`. */ -export function mountFileInspector(container, {api, sender, parentScope, variant, inline = false, promptContext = '', onTagFilter, onRetry, onRefresh, onInteraction = () => {}}) { +export function mountFileInspector(container, {api, sender, parentScope, variant, inline = false, promptContext = '', onTagFilter, onRetry, onRefresh, onInteraction = () => {}, copyFallback = openCopyFallback}) { if (parentScope.signal.aborted) return {setState() {}, dispose() {}}; const scope = childScope(parentScope); let contentScope; @@ -184,7 +205,7 @@ export function mountFileInspector(container, {api, sender, parentScope, variant scope.listen(container, 'keydown', onInteraction); scope.listen(container, 'click', onInteraction); scope.listen(container, 'wheel', onInteraction, {passive:true}); - scope.cleanup(() => {contentScope?.dispose(); container.replaceChildren(); container.classList.remove('file-inspector');}); + scope.cleanup(() => {contentScope?.dispose(); container.replaceChildren(); container.classList.remove('file-inspector'); container.removeAttribute('aria-busy');}); const full = (variant ?? (inline ? 'panel' : 'full')) === 'full'; function statusView(state, parent) { @@ -203,6 +224,8 @@ export function mountFileInspector(container, {api, sender, parentScope, variant if (scope.signal.aborted) return; contentScope?.dispose(); contentScope = childScope(scope); container.replaceChildren(); + // A local read resolves on this thread in bounded steps; the busy state stays until its answer lands. + if (state.loading) container.setAttribute('aria-busy', 'true'); else container.removeAttribute('aria-busy'); render(state); } /** @@ -244,7 +267,7 @@ export function mountFileInspector(container, {api, sender, parentScope, variant inner.append(tags); } inner.append(...generationFacts(record, 'meta-grid', 'small')); - if (full) inner.append(provenance(record, badge), rawMetadata(record)); + if (full) inner.append(summaryButton(record), provenance(record, badge), rawMetadata(record)); const footer = full ? container : el('div', undefined, 'detail-footer'), roles = promptRoles(record.prompts); if (Object.hasOwn(roles, 'positive') && Object.hasOwn(roles, 'negative')) { const pair = createButton('', 'send'); @@ -264,6 +287,23 @@ export function mountFileInspector(container, {api, sender, parentScope, variant } if (!full && footer.childNodes.length) container.append(footer); } + /** + * D117 (LI-4): "Copy settings summary" after the six facts, the legacy COPY ALL. It copies as the concept's prompt + * copy does: the shared toast, or the select-to-copy dialog where the clipboard is unavailable or refused. + */ + function summaryButton(record) { + const button = createButton('Copy settings summary', 'settings-summary'), text = settingsSummary(record); + contentScope.listen(button, 'click', async () => { + try { + if (!navigator.clipboard) throw new Error('Clipboard requires a secure context'); + await navigator.clipboard.writeText(text); + if (!contentScope.signal.aborted) showWorkspaceToast('Settings summary copied.'); + } catch { + if (!contentScope.signal.aborted) copyFallback(text, {scope:contentScope, trigger:button, title:'Copy settings summary'}); + } + }); + return button; + } /** The concept's plain cover; the card image opens the viewer (D19). Video keeps its own element. */ function cover(record) { const {file} = record, video = file?.media_type === 'video'; diff --git a/web/js/workspace/inspect.mjs b/web/js/workspace/inspect.mjs index 39fe9ec..719b067 100644 --- a/web/js/workspace/inspect.mjs +++ b/web/js/workspace/inspect.mjs @@ -7,6 +7,7 @@ import { pageHeading } from './heading.mjs'; import { createWorkspaceIcon } from './icons.mjs'; import { createLocalSession, LOCAL_SESSION_MESSAGES } from './local-session.mjs'; import { localFileAdapter } from './local-inspection.mjs'; +import { loadInspectionSemantics } from './local-semantics.mjs'; import { createMediaViewer } from './media-viewer.mjs'; import { showWorkspaceToast, TOAST_MS } from './toast.mjs'; @@ -72,6 +73,8 @@ export function mountInspect(main, { parentScope, api, sender }) { if (parentScope.signal.aborted) { scope.dispose(); return { dispose }; } parentScope.signal.addEventListener('abort', dispose, { once: true }); scope.cleanup(() => parentScope.signal.removeEventListener('abort', dispose)); + // The node table the local roles resolve with, read before any file is chosen (one request per page). + loadInspectionSemantics(); // The concept DOM: section.surface > h2, p; div.file-drop.spaced-20 > icon, label, input, span.small; #local-preview. const surface = element('section', 'surface'); diff --git a/web/js/workspace/local-inspection.mjs b/web/js/workspace/local-inspection.mjs index 3ccae32..e68889b 100644 --- a/web/js/workspace/local-inspection.mjs +++ b/web/js/workspace/local-inspection.mjs @@ -6,12 +6,11 @@ import { readVideoTags, selectVideoCarrier } from './local-video.mjs'; import { projectMetadata, fitInspectionPayload, MAX_RESPONSE_BYTES } from './local-projection.mjs'; import { projectInspectionPayload } from './inspection-state.mjs'; +import { resolveLocalEvidence, unreadableEvidence } from './local-resolver.mjs'; +import { loadInspectionSemantics } from './local-semantics.mjs'; export const LOCAL_OBSERVATION = 'selected-local-file'; export const LOCAL_SOURCE_LABEL = 'Selected local file'; -// Interim roles until PR L3 ports the inspection resolver: every role is open, and -// the legacy fill in projectInspectionPayload shows what the legacy pages show. -const LOCAL_RESOLUTION_REASON = 'Resolved in this browser from the workflow.'; const LOCAL_LIBRARY = Object.freeze({ status: 'unavailable', scope: 'saved-library', tags: [], category_scope: null, tags_scope: null }); const LOCAL_SCOPE = 'local'; const PREFIX_BYTES = 32; @@ -19,6 +18,24 @@ const MAX_FILENAME_CHARS = 255; const MEDIA_TYPES = new Set(['image', 'video']); const object = value => value !== null && typeof value === 'object' && !Array.isArray(value); +const abortError = () => new DOMException('The local selection ended', 'AbortError'); + +/** `promise`, or an AbortError as soon as `signal` aborts (the work behind `promise` is shared and keeps going). */ +function untilAborted(promise, signal) { + if (!signal) return promise; + if (signal.aborted) return Promise.reject(abortError()); + return new Promise((resolve, reject) => { + const onAbort = () => reject(abortError()); + signal.addEventListener('abort', onAbort, { once: true }); + promise.then(value => { signal.removeEventListener('abort', onAbort); resolve(value); }, + error => { signal.removeEventListener('abort', onAbort); reject(error); }); + }); +} + +/** One turn of the event loop between bounded steps, so the busy state paints and input is handled. */ +function nextTurn(signal) { + return untilAborted(new Promise(resolve => setTimeout(resolve, 0)), signal); +} const pngReader = () => globalThis.PngMetadata || globalThis.window?.PngMetadata; /** A display name with no path separators or control characters; never empty. */ @@ -88,8 +105,19 @@ export function toInspectionRead(classification, result) { const dimension = value => Number.isSafeInteger(value) && value > 0 ? value : null; -/** The `inspection_version: 1` wire for one local read, before the response budget. */ -export function buildLocalPayload({ read, file, classification }) { +/** The roles for one local read (`{prompts, resolution}`): the bounded parse and resolution step of buildLocalPayload. */ +export function localEvidence(read, classification, semantics = null) { + const inspection = toInspectionRead(classificationOf(classification), read); + return inspection.read === null ? unreadableEvidence() : resolveLocalEvidence(inspection.read.records, semantics); +} + +/** + * The `inspection_version: 1` wire for one local read, before the response budget. Its roles are the server + * inspector's for the same records (local-resolver.mjs with `semantics`, the compiled node table; null answers + * "unavailable" as the server does), so the legacy fill in projectInspectionPayload applies exactly where it does + * for Images. + */ +export function buildLocalPayload({ read, file, classification, semantics = null, evidence = localEvidence(read, classification, semantics) }) { const classified = classificationOf(classification); const inspection = toInspectionRead(classified, read); const filename = sanitizeLocalFilename(file?.name); @@ -101,8 +129,8 @@ export function buildLocalPayload({ read, file, classification }) { observation: LOCAL_OBSERVATION, source_label: LOCAL_SOURCE_LABEL, media_type: classified.media, extension: localExtension(filename), format: inspection.format, size, width: dimension(inspection.width), height: dimension(inspection.height), modified_time: modified, }, - prompts: { positive: { status: 'unresolved' }, negative: { status: 'unresolved' } }, - resolution: { state: 'unresolved', sampler_id: null, reason: LOCAL_RESOLUTION_REASON, reason_code: null, node: null }, + prompts: evidence.prompts, + resolution: evidence.resolution, metadata: projectMetadata(inspection.read), library: { ...LOCAL_LIBRARY, tags: [] }, }; @@ -166,7 +194,12 @@ export const localFileAdapter = Object.freeze({ scope(handle) { owned(handle); return LOCAL_SCOPE; }, // An inert sentinel: the controller's same-key check works and no URL is ever built. inspectionPath(handle) { return `local-file:${owned(handle).key}`; }, - async read(handle, { signal } = {}) { + /** + * Reads, resolves and projects one selection on the page's thread in bounded steps (each bound by the 2 MiB role + * and 4 MiB workflow budgets and the resolver's work limits) with a turn of the event loop between them, so the + * inspector's busy state paints. Every wait ends with the selection's `signal`; `yieldControl` is for tests. + */ + async read(handle, { signal, yieldControl = nextTurn } = {}) { const secret = owned(handle); let result = null; try { @@ -176,7 +209,14 @@ export const localFileAdapter = Object.freeze({ // MetadataReadError, an unreadable record. Abort and programming errors still reject. if (!(error instanceof DOMException) || error.name === 'AbortError' || signal?.aborted) throw error; } - return fitLocalPayload(buildLocalPayload({ read: result, file: { name: secret.filename, size: secret.file.size, lastModified: secret.file.lastModified }, classification: secret.classification }), MAX_RESPONSE_BYTES, { signal }); + const semantics = await untilAborted(loadInspectionSemantics(), signal); + await yieldControl(signal); + const evidence = localEvidence(result, secret.classification, semantics); + await yieldControl(signal); + const file = { name: secret.filename, size: secret.file.size, lastModified: secret.file.lastModified }; + const payload = buildLocalPayload({ read: result, file, classification: secret.classification, semantics, evidence }); + await yieldControl(signal); + return fitLocalPayload(payload, MAX_RESPONSE_BYTES, { signal }); }, toRecord(result, handle, extractFacts) { const secret = owned(handle); diff --git a/web/js/workspace/local-parameters.mjs b/web/js/workspace/local-parameters.mjs new file mode 100644 index 0000000..5e268fd --- /dev/null +++ b/web/js/workspace/local-parameters.mjs @@ -0,0 +1,55 @@ +// A1111 `parameters` for local-resolver.mjs (#249 local Inspect, PR L3 Task 9): a port of +// utils/prompt_pair_resolver.py `_parameters`, `_footer` and `_trailer_lines` for the inspection profile. +// Python's `re` differs from JavaScript's in three ways that matter here, so the patterns spell them out: +// multiline `^`/`$` break only at "\n" (not "\r", U+2028 or U+2029), `\s` is the `str.isspace()` set and `\d` +// is any Unicode decimal digit (Nd). Lengths count code points. No DOM. +import { PY_SPACE, pyLen, pyStrip } from './py-json.mjs'; +import { EMPTY_POSITIVE_REASON, result } from './local-resolver-support.mjs'; + +const START = '(?<=^|\\n)', END = '(?=\\n|$)', SPACE = `[${PY_SPACE}]*`; +// `_FOOTER` and `_BARE_FOOTER` (inspection reads a bare `Steps: N` when there is no full footer). +const FOOTER = new RegExp(`${START}Steps:${SPACE}\\p{Nd}+${SPACE},[^\\n]*${END}`, 'gu'); +const BARE_FOOTER = new RegExp(`${START}Steps:${SPACE}\\p{Nd}+${SPACE}${END}`, 'gu'); +const TRAILERS = ['Template:', 'Negative Template:']; +const DELIMITER = '\nNegative prompt:'; + +/** `_trailer_lines`: empty, or at most one `Template:` line then at most one `Negative Template:` line. */ +function trailerLines(text) { + const stripped = pyStrip(text); + const lines = stripped ? stripped.split(/\r?\n|\r/) : []; + const prefixes = lines.map(line => { + const index = TRAILERS.findIndex(name => line.startsWith(name)); + return index === -1 ? null : index; + }); + return !prefixes.includes(null) && prefixes.every((prefix, index) => index === 0 || prefix > prefixes[index - 1]); +} + +/** `_footer(value, inspection=True)`: the unique settings footer match, or null. */ +function footer(value) { + let footers = [...value.matchAll(FOOTER)]; + if (!footers.length) footers = [...value.matchAll(BARE_FOOTER)]; + if (footers.length !== 1) return null; + const [match] = footers; + return trailerLines(value.slice(match.index + match[0].length)) ? match : null; +} + +const rstripLineBreaks = text => text.replace(/[\r\n]+$/, ''); + +/** `_parameters(value, max_text_length, inspection=True)`. */ +export function parameters(value, maxTextLength) { + if (typeof value !== 'string' || !value) return result('absent', { reason: 'No A1111 parameters' }); + if (pyLen(value) > maxTextLength) return result('unresolved', { reason: 'Parameters exceed the length limit', reasonCode: 'text-limit' }); + const match = footer(value); + if (match === null) return result('unresolved', { reason: 'A1111 settings footer is not unique', reasonCode: 'malformed' }); + // R4: text that starts with the delimiter has an empty positive (#165). + const body = `\n${rstripLineBreaks(value.slice(0, match.index))}`; + const parts = body.split(DELIMITER); + if (parts.length > 2) return result('ambiguous', { reason: 'Multiple negative prompt delimiters' }); + const positive = pyStrip(parts[0]); + if (!positive) return result('unresolved', { reason: EMPTY_POSITIVE_REASON }); + const provenance = { format: 'a1111', field: 'parameters', text_source: 'embedded-parameters' }; + const side = (text, role) => ({ text, storage_text: text, provenance: { ...provenance, role } }); + if (parts.length === 1) return result('absent', { positive: side(positive, 'positive'), reason: 'Negative prompt delimiter is absent' }); + const negative = pyStrip(parts[1]); + return result('resolved', { positive: side(positive, 'positive'), negative: side(negative, 'negative') }); +} diff --git a/web/js/workspace/local-resolver-stages.mjs b/web/js/workspace/local-resolver-stages.mjs new file mode 100644 index 0000000..351d560 --- /dev/null +++ b/web/js/workspace/local-resolver-stages.mjs @@ -0,0 +1,174 @@ +// Candidate selection for local-resolver.mjs (#249 local Inspect, PR L3 Task 9): ports of +// utils/prompt_pair_resolver.py `_GraphResolver` `stage`, `upstream_stages`, `final_stages`, `file_stages`, +// `non_file_outputs`, `producers_of`, `consumers`, `reaches_output`, plus `_outcome_key`, `_recipe_key` and +// `_shared_pair` (#270). Each function takes the resolver whose budgets and caches it spends, so the order of +// work, and with it every limit, is the server's. No DOM. +import { isDict, pyGet, pyStr } from './py-json.mjs'; +import { DETAILER, IDENTICAL_BRANCHES_REASON, Unresolved, isLink, result } from './local-resolver-support.mjs'; + +const roleText = side => side !== null && typeof side === 'object' ? side.text : null; +const storageText = side => side !== null && typeof side === 'object' ? side.storage_text : null; +/** `_outcome_key`: what a reader sees of a result, the state and the two role texts. */ +export const outcomeKey = item => JSON.stringify([item.state, roleText(item.positive), roleText(item.negative)]); +/** `_recipe_key`: the outcome plus each side's stored recipe. */ +const recipeKey = item => JSON.stringify([item.state, roleText(item.positive), roleText(item.negative), storageText(item.positive), storageText(item.negative)]); + +/** `_shared_pair`: the one pair every sampler branch resolved to, or null (#270). */ +export function sharedPair(candidates) { + const first = candidates[0]; + if (first.state !== 'resolved') return null; + if (new Set(candidates.map(recipeKey)).size !== 1) return null; + return result('resolved', { positive: first.positive, negative: first.negative, reason: IDENTICAL_BRANCHES_REASON, candidates }); +} + +/** `stage`: one sampler's result; a detailer is compared with its upstream stages. */ +export function stage(resolver, samplerId, later) { + if (later.size >= resolver.maxDepth) return result('unresolved', { samplerId, reason: 'Resolution depth limit reached', reasonCode: 'depth-limit' }); + const own = resolver.sides(samplerId); + if (own.state === 'unresolved') return own; + const [name, inputs] = resolver.node(samplerId); + const entry = resolver.semantics.samplers.get(name); + if (entry === undefined || entry.strategy !== DETAILER) return own; + let upstream; + try { + upstream = upstreamStages(resolver, samplerId, pyGet(inputs, entry.image_stage)); + if (upstream.some(nodeId => later.has(nodeId))) throw new Unresolved('Cyclic sampler stage ancestry', 'malformed'); + } catch (error) { + if (!(error instanceof Unresolved)) throw error; + return result('unresolved', { samplerId, reason: error.message, reasonCode: error.code, node: error.node }); + } + if (!upstream.length) return own; + const deeper = new Set([...later, samplerId]); + const stages = upstream.map(nodeId => stage(resolver, nodeId, deeper)); + const blocked = stages.find(item => item.state === 'unresolved'); + // A stage that cannot be read cannot be compared: never pick one. + if (blocked !== undefined) return result('unresolved', { samplerId, reason: blocked.reason, reasonCode: blocked.reason_code, node: blocked.node }); + const flat = []; + for (const item of [own, ...stages]) flat.push(...(item.state === 'ambiguous' ? item.candidates : [item])); + if (new Set(flat.map(outcomeKey)).size === 1) return own; + return result('ambiguous', { samplerId, reason: 'Sampler stages have different prompts', candidates: flat, reasonCode: 'multistage-differs' }); +} + +/** `upstream_stages`: samplers reached from a detailer's image input, breadth first; each node draws a visit. */ +function upstreamStages(resolver, origin, value) { + if (!isLink(value)) throw new Unresolved('Expected an image link', 'malformed'); + const found = [], start = String(value[0]), queue = [[start, 0]], queued = new Set([start]); + for (let head = 0; head < queue.length; head++) { + const [nodeId, depth] = queue[head]; + if (nodeId === origin) throw new Unresolved('Cyclic sampler stage ancestry', 'malformed'); + if (depth >= resolver.maxDepth) throw new Unresolved('Resolution depth limit reached', 'depth-limit'); + resolver.budget.spend(); + const [name, inputs] = resolver.node(nodeId); + if (resolver.stageClasses.has(name)) { found.push(nodeId); continue; } + if (resolver.stageShaped(name, inputs)) throw resolver.unsupported('Unsupported sampler stage ancestry', nodeId); + resolver.enqueue(queue, queued, inputs, depth + 1); + } + return found; +} + +const strategyOf = (resolver, nodeId) => resolver.semantics.samplers.get(resolver.graph.get(nodeId).get('class_type')).strategy; + +/** `final_stages`: drop samplers that only feed detailers (each is judged in that chain). */ +export function finalStages(resolver, samplerIds) { + samplerIds = fileStages(resolver, samplerIds); + const detailers = samplerIds.filter(nodeId => strategyOf(resolver, nodeId) === DETAILER); + if (!detailers.length) return samplerIds; + let reverse; + try { reverse = consumers(resolver); } catch (error) { + if (!(error instanceof Unresolved)) throw error; + return samplerIds; + } + const absorbed = new Set(); + for (const detailer of detailers) { + resolver.budget.reset(resolver.perCandidateVisits); + try { + const [name, inputs] = resolver.node(detailer); + const image = pyGet(inputs, resolver.semantics.samplers.get(name).image_stage); + for (const nodeId of upstreamStages(resolver, detailer, image)) { + if (!reachesOutput(resolver, nodeId, reverse)) absorbed.add(nodeId); + } + } catch (error) { + if (!(error instanceof Unresolved)) throw error; + } + } + const kept = samplerIds.filter(nodeId => !absorbed.has(nodeId)); + return kept.length ? kept : samplerIds; +} + +/** `file_stages`: stages not proven preview-only; all of them when every one is. */ +function fileStages(resolver, samplerIds) { + if (samplerIds.length < 2) return samplerIds; + let toFile, toPreview; + try { + const reverse = consumers(resolver), previews = nonFileOutputs(resolver); + const terminals = [...resolver.graph].filter(([nodeId, node]) => isDict(node) && !previews.has(nodeId) && !reverse.get(nodeId)?.length).map(([nodeId]) => nodeId); + toFile = producersOf(resolver, terminals, previews); + toPreview = producersOf(resolver, [...previews], previews); + } catch (error) { + if (!(error instanceof Unresolved)) throw error; + return samplerIds; + } + const kept = samplerIds.filter(nodeId => toFile.has(nodeId) || !toPreview.has(nodeId)); + return kept.length ? kept : samplerIds; +} + +function nonFileOutputs(resolver) { + const names = resolver.semantics.nonFileOutputs, found = new Set(); + for (const [nodeId, node] of resolver.graph) { + // `node.get("class_type") in names`: only a string can be a listed class. + if (isDict(node) && names.has(pyGet(node, 'class_type'))) found.add(nodeId); + } + return found; +} + +/** `producers_of`: nodes whose output reaches one of `starts`, never through a preview. */ +function producersOf(resolver, starts, previews) { + const found = new Set(starts), queue = [...starts]; + for (let head = 0; head < queue.length; head++) { + const inputs = pyGet(resolver.graph.get(queue[head]), 'inputs'); + if (!isDict(inputs)) continue; + resolver.scan(inputs.size); + for (const value of inputs.values()) { + if (!isLink(value)) continue; + const producer = String(value[0]); + if (found.has(producer) || previews.has(producer) || !isDict(pyGet(resolver.graph, producer))) continue; + found.add(producer); + queue.push(producer); + } + } + return found; +} + +/** `consumers`: reverse links, node ID to the IDs of nodes reading one of its outputs. */ +function consumers(resolver) { + const reverse = new Map(); + for (const [nodeId, node] of resolver.graph) { + if (!isDict(node) || !isDict(pyGet(node, 'inputs'))) continue; + const inputs = node.get('inputs'); + resolver.scan(inputs.size); + for (const value of inputs.values()) { + if (!isLink(value)) continue; + const producer = String(value[0]); + if (!reverse.has(producer)) reverse.set(producer, []); + reverse.get(producer).push(nodeId); + } + } + return reverse; +} + +/** `reaches_output`: whether a sampler's output reaches a terminal node besides later stages. */ +function reachesOutput(resolver, nodeId, reverse) { + const seen = new Set([nodeId]), queue = [nodeId]; + for (let head = 0; head < queue.length; head++) { + for (const consumer of reverse.get(queue[head]) ?? []) { + if (seen.has(consumer)) continue; + seen.add(consumer); + resolver.budget.spend(); + const name = pyStr(pyGet(resolver.graph.get(consumer), 'class_type', '')); + if (resolver.stageClasses.has(name) || resolver.semantics.nonFileOutputs.has(name)) continue; + if (!reverse.get(consumer)?.length) return true; + queue.push(consumer); + } + } + return false; +} diff --git a/web/js/workspace/local-resolver-support.mjs b/web/js/workspace/local-resolver-support.mjs new file mode 100644 index 0000000..f180e07 --- /dev/null +++ b/web/js/workspace/local-resolver-support.mjs @@ -0,0 +1,255 @@ +// Tables, evidence reader, bounds and outcome lines for local-resolver.mjs (#249 local Inspect, PR L3 Tasks 8-9): +// the constants of utils/prompt_pair_resolver.py and utils/inspection_outcomes.py, utils/pair_execution.py +// `read_pair_execution` and the semantics table check of utils/inspection_semantics.py. No DOM. +import { PyFloat, PyValueError, isDict, isList, isInt, pyJsonLoads, pyLen, pySlice, pyStrip, pyTruthy, pyEqualsOne, pyStr, pyGet } from './py-json.mjs'; + +/** The semantics table is unusable: the server's `SemanticsError`. */ +export class SemanticsError extends Error { + constructor(message) { + super(message); + this.name = 'SemanticsError'; + } +} + +// INSPECTION_PROFILE (prompt_pair_resolver.py 152-166); its drop_preview_only_stages is always on here. +export const PROFILE = Object.freeze({ + perCandidateVisits: 2000, totalVisits: 20000, maxDepth: 64, maxTextLength: 100000, nodeCeiling: 20000, + maxPathEntries: 64 * 20000, maxBuiltChars: 16 * 100000, maxScannedUnits: 8000000, +}); +export const EXECUTION_KEY = 'comfyassets_prompt_pairs'; +export const ROLE_METADATA_KEYS = new Set(['prompt', 'parameters', EXECUTION_KEY]); +// pair_execution.py +export const MAX_EXECUTION_RECORDS = 16, MAX_EXECUTION_NODES = 64, MAX_EXECUTION_TEXT = 100000, MAX_EXECUTION_JSON = 500000; +export const EXECUTION_FIELDS = ['text', 'negative_text', 'positive_text', 'negative_effective_text', 'prepend_text', 'append_text']; + +export const CANDIDATE_STRATEGIES = new Set(['ksampler', 'custom-advanced', 'detailer-stage']); +export const DETAILER = 'detailer-stage'; +export const GUIDER_ABSENT_REASON = 'Guider has no negative input'; +export const ZEROED_SOURCE = 'zeroed-conditioning'; +export const MAX_BRANCH_CANDIDATES = 32; +export const RUNTIME_REASON = 'Text is decided at run time'; +export const EMPTY_POSITIVE_REASON = 'Positive prompt is empty'; +export const IDENTICAL_BRANCHES_REASON = 'Every sampler branch uses the same prompt pair'; +export const MULTISTAGE_UNATTRIBUTED_REASON = 'Multistage sampler ancestry is ambiguous'; +export const MALFORMED_EVIDENCE_REASON = 'Prompt evidence is malformed'; +export const UNREADABLE_METADATA_REASON = 'Media metadata could not be read'; +export const SEMANTICS_UNAVAILABLE_REASON = 'Inspection node semantics are unavailable'; +export const INCOMPATIBLE_SLOT = 'Output slot has an incompatible type'; +export const OVERWRITTEN_PROMPT_REASON = 'Saved PromptManager text was overwritten by another node'; +export const UNVERIFIABLE_CODES = new Set(['unsupported-node', 'runtime-value']); +export const MAX_JOIN_INPUTS = 1000; +export const SAMPLER_LIKE_INPUTS = ['latent_image', 'guider', 'positive', 'negative']; +export const NO_SAMPLER_NAMES = 3; +export const CLASS_NAME_LENGTH = 64; +export const MAX_SUBGRAPH_DEPTH = 8, MAX_WORKFLOW_NODES = 100000; + +// inspection_outcomes.py +export const OUTCOME_NAME_LENGTH = 200; +export const LIMIT_CODES = ['work-limit', 'depth-limit', 'text-limit', 'graph-ceiling']; +export const NAMED_LINES = { + 'unsupported-node': 'Prompt uses a node the inspector does not support', + 'runtime-value': 'Prompt is chosen at run time', + composite: 'Prompt combines several texts', +}; +export const CODED_LINES = { + ...Object.fromEntries(LIMIT_CODES.map(code => [code, 'Prompt exceeds inspection limits.'])), + 'no-sampler': 'No supported sampler was found.', + malformed: 'Prompt metadata in this file is malformed.', + 'multistage-differs': 'Sampler stages have different prompts.', +}; +export const UNCODED_LINES = { + [EMPTY_POSITIVE_REASON]: 'Positive prompt is empty.', + [MULTISTAGE_UNATTRIBUTED_REASON]: 'Several sampler stages were found; their prompts were not compared.', + [SEMANTICS_UNAVAILABLE_REASON]: "The inspector's node table is unavailable.", + [UNREADABLE_METADATA_REASON]: 'Metadata in this file could not be read.', +}; + +// Output adapters (prompt_pair_resolver.py 44-105): [inputName, kind, {compose, storageInput, comma, strip, default}]. +export const adapter = (inputName, kind, options = {}) => Object.freeze({ inputName, kind, compose: false, storageInput: false, comma: false, strip: false, default: null, ...options }); +export const slotKey = (name, slot) => `${name}\u0000${String(slot)}`; +export const ADAPTERS = new Map(); +for (const name of ['PromptManager', 'PromptManagerFocused', 'PromptManagerSplit']) { + ADAPTERS.set(slotKey(name, 0), adapter('text', 'conditioning', { compose: true })); + ADAPTERS.set(slotKey(name, 1), adapter('text', 'string', { compose: true })); +} +ADAPTERS.set(slotKey('PromptManagerPair', 0), adapter('text', 'conditioning', { compose: true })); +ADAPTERS.set(slotKey('PromptManagerPair', 2), adapter('text', 'string', { compose: true })); +ADAPTERS.set(slotKey('PromptManagerPair', 1), adapter('negative_text', 'conditioning', { storageInput: true })); +ADAPTERS.set(slotKey('PromptManagerPair', 3), adapter('negative_text', 'string', { storageInput: true })); +ADAPTERS.set(slotKey('PromptManagerText', 0), adapter('text', 'string', { compose: true })); +ADAPTERS.set(slotKey('CLIPTextEncode', 0), adapter('text', 'conditioning')); +for (const name of ['PrimitiveString', 'PrimitiveStringMultiline']) ADAPTERS.set(slotKey(name, 0), adapter('value', 'string')); +for (const name of ['Text Multiline', 'String Literal', 'ShowText|pysssss']) ADAPTERS.set(slotKey(name, 0), adapter('text', 'string')); +// Historical PromptManager classes (inspection only). +export const COMMA = { comma: true }, NEGATIVE = { strip: true, default: '' }; +const historical = [ + ['PromptManagerV2', 0, 'text', 'conditioning', COMMA], ['PromptManagerV2', 1, 'negative_text', 'conditioning', NEGATIVE], + ['PromptManagerV2', 2, 'text', 'string', COMMA], ['PromptManagerV2', 3, 'negative_text', 'string', NEGATIVE], + ['PromptManagerV2Text', 0, 'text', 'string', COMMA], ['PromptManagerV2Text', 1, 'negative_text', 'string', NEGATIVE], + ['PromptManagerNegative', 0, 'text', 'conditioning', { strip: true }], ['PromptManagerNegative', 1, 'text', 'string', { strip: true }], + ['PromptManagerPositiveText', 0, 'text', 'string', COMMA], ['PromptManagerNegativeText', 0, 'text', 'string', COMMA], +]; +for (const name of ['PromptManagerPositive', 'PromptManagerDetailer']) historical.push([name, 0, 'text', 'conditioning', COMMA], [name, 1, 'text', 'string', COMMA]); +for (const [name, slot, input, kind, options] of historical) ADAPTERS.set(slotKey(name, slot), adapter(input, kind, options)); +// `known_slots` in execution_record: every adapter slot per class. +export const ADAPTER_SLOTS = new Map(); +for (const key of ADAPTERS.keys()) { + const [name, slot] = key.split('\u0000'); + if (!ADAPTER_SLOTS.has(name)) ADAPTER_SLOTS.set(name, new Set()); + ADAPTER_SLOTS.get(name).add(slot); +} + +export class Unresolved extends Error { + constructor(message, code = null, node = null) { + super(message); + this.code = code; + this.node = node; + } +} +export class Diverging extends Error { + constructor(key) { + super('diverging'); + this.key = key; + } +} + +/** `_link`: a two-item list of (str or int) and a non-negative int, never a bool. */ +export function isLink(value) { + if (!isList(value) || value.length !== 2) return false; + const [source, slot] = value; + return (typeof source === 'string' || isInt(source)) && isInt(slot) && (typeof slot === 'bigint' ? slot >= 0n : slot >= 0); +} +export const nodeRef = (nodeId, classType) => ({ id: pySlice(nodeId, CLASS_NAME_LENGTH), class_type: typeof classType === 'string' ? pySlice(classType, CLASS_NAME_LENGTH) : null }); + +export function result(state, { positive = null, negative = null, samplerId = null, reason = '', candidates = [], reasonCode = null, node = null } = {}) { + return { state, positive, negative, sampler_id: samplerId, reason, candidates, reason_code: reasonCode, node }; +} + +export class Budget { + constructor(total) { + this.total = total; + this.allowance = total; + } + reset(allowance) { this.allowance = allowance; } + spend() { + if (this.total <= 0 || this.allowance <= 0) throw new Unresolved('Resolution visit limit reached', 'work-limit'); + this.total -= 1; + this.allowance -= 1; + } + charge(cost) { + if (cost > this.allowance) throw new Unresolved('Resolution visit limit reached', 'work-limit'); + this.allowance -= cost; + } +} + +/** `read_pair_execution`: one distinct record for a traced node, or null; malformed evidence throws `Unresolved`. */ +export function readPairExecution(metadata, nodeId) { + const evidence = message => new Unresolved(message, 'malformed'); + if (!isDict(metadata) || !metadata.has(EXECUTION_KEY)) return null; + let envelope = metadata.get(EXECUTION_KEY); + if (typeof envelope === 'string') { + if (pyLen(envelope) > MAX_EXECUTION_JSON) throw evidence('Execution evidence exceeds the size limit'); + try { envelope = pyJsonLoads(envelope); } catch (error) { + if (error instanceof PyValueError) throw evidence('Malformed execution evidence JSON'); + throw error; + } + } + if (!isDict(envelope) || !pyEqualsOne(pyGet(envelope, 'version'))) throw evidence('Unsupported execution evidence format'); + const nodes = pyGet(envelope, 'nodes'); + if (pyTruthy(pyGet(envelope, 'truncated')) || !isDict(nodes) || nodes.size > MAX_EXECUTION_NODES) throw evidence('Truncated or malformed execution evidence'); + if (!nodes.has(nodeId)) return null; + const node = nodes.get(nodeId); + if (!isDict(node) || pyTruthy(pyGet(node, 'truncated'))) throw evidence('Truncated or malformed node execution evidence'); + const records = pyGet(node, 'records'); + if (!isList(records) || !records.length || records.length > MAX_EXECUTION_RECORDS) throw evidence('Malformed node execution records'); + const unique = new Map(); + for (const record of records) { + if (!isDict(record) || EXECUTION_FIELDS.some(key => typeof pyGet(record, key) !== 'string' || pyLen(record.get(key)) > MAX_EXECUTION_TEXT)) { + throw evidence('Malformed execution text values'); + } + const clean = Object.fromEntries(EXECUTION_FIELDS.map(key => [key, record.get(key)])); + if (clean.negative_effective_text !== clean.negative_text) throw evidence('Negative execution text must be unchanged'); + unique.set(JSON.stringify(EXECUTION_FIELDS.map(key => clean[key])), clean); + } + if (unique.size !== 1) throw evidence('Multiple distinct executions have no image anchor'); + return [...unique.values()][0]; +} + +/** + * The validated semantics table (utils/inspection_semantics.py), from the parsed JSON document. Throws + * `SemanticsError` for any shape the server rejects; the caller then answers "semantics unavailable". + */ +export function compileSemantics(doc) { + const fail = message => { throw new SemanticsError(message); }; + const plain = value => value !== null && typeof value === 'object' && !Array.isArray(value); + if (!plain(doc) || doc.schema !== 1) fail('unsupported semantics table'); + const owners = new Map(); + const claim = (name, category) => { + if (owners.has(name) && owners.get(name) !== category) fail(`duplicate class ${name}`); + owners.set(name, category); + }; + const byClass = category => { + if (!plain(doc[category])) fail(`category ${category} must be an object`); + const table = new Map(); + for (const [name, entry] of Object.entries(doc[category])) { + if (!plain(entry) || typeof entry.strategy !== 'string') fail(`${category}[${name}]`); + claim(name, category); + table.set(name, entry); + } + return table; + }; + const bySlot = category => { + if (!Array.isArray(doc[category])) fail(`category ${category} must be a list`); + const table = new Map(); + for (const row of doc[category]) { + if (!plain(row) || typeof row.class !== 'string' || !Number.isInteger(row.slot) || row.slot < 0 || row.slot > 255) fail(`${category} row`); + const key = slotKey(row.class, row.slot); + if (table.has(key)) fail(`${category}: duplicate output key`); + claim(row.class, category); + const { class: _name, slot: _slot, ...entry } = row; + table.set(key, entry); + } + return table; + }; + const bySet = category => { + if (!Array.isArray(doc[category])) fail(`category ${category} must be a list`); + const set = new Set(); + for (const name of doc[category]) { + if (typeof name !== 'string' || set.has(name)) fail(`${category}: duplicate class`); + claim(name, category); + set.add(name); + } + return set; + }; + const samplers = byClass('samplers'), guiders = byClass('guiders'), selectors = byClass('selectors'); + const composites = byClass('composites'), savers = byClass('savers'); + const conditioning = bySlot('conditioning'), encoders = bySlot('encoders'), strings = bySlot('strings'); + const runtime = bySet('runtime'), nonFileOutputs = bySet('non_file_outputs'); + const stageInputs = doc.stage_inputs; + if (!plain(stageInputs) || !Array.isArray(stageInputs.shaped) || !Array.isArray(stageInputs.with_model)) fail('stage_inputs'); + return Object.freeze({ + samplers, guiders, selectors, composites, savers, conditioning, encoders, strings, runtime, nonFileOutputs, + stageInputs: { shaped: [...stageInputs.shaped], withModel: [...stageInputs.with_model] }, allClasses: new Set(owners.keys()), + }); +} + +/** `outcome_message`: one line for an unresolved outcome, or null to keep the status copy. */ +export function outcomeMessage(resolution) { + if (resolution?.state !== 'unresolved') return null; + const code = typeof resolution.reason_code === 'string' ? resolution.reason_code : null; + if (Object.hasOwn(NAMED_LINES, code)) { + const node = resolution.node, raw = node !== null && typeof node === 'object' ? node.class_type : null; + const name = typeof raw === 'string' && raw ? pySlice(raw, OUTCOME_NAME_LENGTH) : null; + return name ? `${NAMED_LINES[code]} (${name}).` : `${NAMED_LINES[code]}.`; + } + if (code === null) return Object.hasOwn(UNCODED_LINES, resolution.reason) ? UNCODED_LINES[resolution.reason] : null; + return Object.hasOwn(CODED_LINES, code) ? CODED_LINES[code] : null; +} + +export const sideOf = (status, text = null, source = null) => ({ status, text, source }); +export function explained(prompts, resolution) { + const message = outcomeMessage(resolution); + if (message === null) return prompts; + return Object.fromEntries(Object.entries(prompts).map(([role, side]) => [role, side.status === 'unresolved' && !Object.hasOwn(side, 'message') ? { ...side, message } : side])); +} +export const EMPTY_POSITIVE = outcomeMessage({ state: 'unresolved', reason: EMPTY_POSITIVE_REASON }); diff --git a/web/js/workspace/local-resolver.mjs b/web/js/workspace/local-resolver.mjs new file mode 100644 index 0000000..3e2b5bb --- /dev/null +++ b/web/js/workspace/local-resolver.mjs @@ -0,0 +1,772 @@ +// The server's inspection resolver in this browser (#249 local Inspect, PR L3 Task 8, decision LI-1): a port of +// utils/prompt_inspector.py `inspect_prompt_evidence` with utils/prompt_pair_resolver.py (INSPECTION_PROFILE) and +// utils/pair_execution.py `read_pair_execution`, driven by web/js/inspection-semantics.json. Python is the oracle: +// tests/test_local_inspect_parity.py compares every answer with the server's on the same records. Values follow +// Python's model (py-json.mjs): dict order, int versus float, code-point lengths, `str.strip()`. +// +// Task 8 ported execution evidence and graph tracing for one sampler; Task 9 adds candidate selection among several +// samplers and detailer stages (local-resolver-stages.mjs) and A1111 `parameters` (local-parameters.mjs). No DOM. +import { PyValueError, isDict, isList, isInt, pyJsonLoads, pyLen, pySlice, pyStrip, pyStr, pyGet } from './py-json.mjs'; +import { + ADAPTERS, + ADAPTER_SLOTS, + Budget, + CANDIDATE_STRATEGIES, + CLASS_NAME_LENGTH, + Diverging, + EMPTY_POSITIVE, + EMPTY_POSITIVE_REASON, + GUIDER_ABSENT_REASON, + INCOMPATIBLE_SLOT, + MALFORMED_EVIDENCE_REASON, + MAX_BRANCH_CANDIDATES, + MAX_JOIN_INPUTS, + MAX_SUBGRAPH_DEPTH, + MAX_WORKFLOW_NODES, + MULTISTAGE_UNATTRIBUTED_REASON, + NO_SAMPLER_NAMES, + OVERWRITTEN_PROMPT_REASON, + PROFILE, + ROLE_METADATA_KEYS, + RUNTIME_REASON, + SAMPLER_LIKE_INPUTS, + SEMANTICS_UNAVAILABLE_REASON, + UNREADABLE_METADATA_REASON, + UNVERIFIABLE_CODES, + Unresolved, + ZEROED_SOURCE, + compileSemantics, + explained, + isLink, + nodeRef, + readPairExecution, + result, + sideOf, + slotKey, +} from './local-resolver-support.mjs'; +import { finalStages, outcomeKey, sharedPair, stage } from './local-resolver-stages.mjs'; +import { parameters } from './local-parameters.mjs'; + +export { SemanticsError, compileSemantics, readPairExecution, outcomeMessage, isLink } from './local-resolver-support.mjs'; + +class GraphResolver { + constructor(graph, metadata, semantics, overwritten) { + this.graph = graph; + this.overwritten = overwritten; + this.perCandidateVisits = PROFILE.perCandidateVisits; + this.budget = new Budget(PROFILE.totalVisits); + this.budget.reset(PROFILE.perCandidateVisits); + this.pathEntries = PROFILE.maxPathEntries; + this.builtChars = PROFILE.maxBuiltChars; + this.scanned = PROFILE.maxScannedUnits; + this.checked = new Map(); + this.costs = new Map(); + this.heights = new Map(); + this.deepest = 0; + this.maxDepth = PROFILE.maxDepth; + this.maxTextLength = PROFILE.maxTextLength; + this.memo = new Map(); + this.active = new Set(); + this.metadata = metadata ?? new Map(); + this.textSources = new Map(); + this.choices = new Map(); + this.tainted = false; + this.latentWalks = new Map(); + this.latentCharged = new Set(); + this.semantics = semantics; + this.samplerClasses = new Set([...semantics.samplers].filter(([, entry]) => CANDIDATE_STRATEGIES.has(entry.strategy)).map(([name]) => name)); + this.stageClasses = new Set(semantics.samplers.keys()); + } + + node(nodeId) { + if (!this.checked.has(nodeId)) { + try { + this.checked.set(nodeId, this.checkedNode(nodeId)); + } catch (error) { + if (!(error instanceof Unresolved) || error.code === 'work-limit') throw error; + this.checked.set(nodeId, error); + } + } + const checked = this.checked.get(nodeId); + if (checked instanceof Unresolved) throw new Unresolved(checked.message, checked.code, checked.node); + return checked; + } + checkedNode(nodeId) { + const node = pyGet(this.graph, nodeId); + if (!isDict(node) || !isDict(pyGet(node, 'inputs'))) throw new Unresolved('Missing or malformed graph node', 'malformed'); + const inputs = node.get('inputs'); + this.scan(inputs.size); + return [pyStr(pyGet(node, 'class_type', '')), inputs]; + } + scan(units) { + if (units > this.scanned) { + this.scanned = -1; + throw new Unresolved('Resolution work limit reached', 'work-limit'); + } + this.scanned -= units; + } + unsupported(message, nodeId) { return this.named(message, 'unsupported-node', nodeId); } + named(message, code, nodeId) { + const node = pyGet(this.graph, nodeId); + const classType = isDict(node) ? pyGet(node, 'class_type') : null; + return new Unresolved(message, code, nodeRef(nodeId, classType)); + } + bounded(text) { + if (pyLen(text) > this.maxTextLength) throw new Unresolved('Resolved text exceeds the length limit', 'text-limit'); + return text; + } + built(text) { + this.builtChars -= pyLen(text); + if (this.builtChars < 0) throw new Unresolved('Resolution work limit reached', 'work-limit'); + return text; + } + + /** `text`: [text, path, storageText] for a string value or a typed link. */ + text(value, kind, depth = 0) { + this.deepest = Math.max(this.deepest, depth); + if (depth >= this.maxDepth) throw new Unresolved('Resolution depth limit reached', 'depth-limit'); + if (typeof value === 'string' && kind === 'string') return [this.bounded(value), [], value]; + if (!isLink(value)) throw new Unresolved('Expected a typed graph link or text input', 'malformed'); + const nodeId = String(value[0]), slot = value[1]; + const key = `${slotKey(nodeId, slot)}\u0000${kind}`; + if (this.active.has(key)) throw new Unresolved('Cyclic prompt graph', 'malformed'); + if (this.memo.has(key)) { + const height = this.heights.get(key); + if (depth + height >= this.maxDepth) throw new Unresolved('Resolution depth limit reached', 'depth-limit'); + this.budget.charge(this.costs.get(key)); + this.deepest = Math.max(this.deepest, depth + height); + return this.memo.get(key); + } + const allowance = this.budget.allowance, outerDeepest = this.deepest, outerTainted = this.tainted; + this.tainted = false; + this.deepest = depth; + try { + this.budget.spend(); + const [name, inputs] = this.node(nodeId); + this.scan(inputs.size); + if (this.overwritten.has(nodeId)) throw new Unresolved(OVERWRITTEN_PROMPT_REASON, 'malformed'); + this.active.add(key); + let text, path, storageText; + const adapted = ADAPTERS.get(slotKey(name, slot)); + if (name === 'Reroute' && slot === 0) { + const keys = ['value', 'input', 'in'].filter(item => inputs.has(item)); + if (keys.length !== 1) throw new Unresolved('Reroute input is not uniquely identifiable', 'malformed'); + [text, path, storageText] = this.text(inputs.get(keys[0]), kind, depth + 1); + this.inheritSource(nodeId, slot, [path]); + } else if (adapted) { + if (adapted.kind !== kind) throw new Unresolved(INCOMPATIBLE_SLOT, 'malformed'); + const evidence = name === 'PromptManagerPair' ? this.executionRecord(nodeId, inputs) : null; + if (evidence !== null) { + text = evidence[adapted.inputName === 'text' ? 'positive_text' : 'negative_effective_text']; + storageText = evidence[adapted.inputName]; + path = []; + this.textSources.set(slotKey(nodeId, slot), 'execution'); + } else if (adapted.comma || adapted.strip) { + [text, path, storageText] = this.historical(adapted, inputs, depth); + } else { + [text, path, storageText] = this.text(pyGet(inputs, adapted.inputName), 'string', depth + 1); + if (adapted.compose || adapted.storageInput) storageText = text; + if (adapted.compose) { + const [before, beforePath] = this.text(pyGet(inputs, 'prepend_text', ''), 'string', depth + 1); + const [after, afterPath] = this.text(pyGet(inputs, 'append_text', ''), 'string', depth + 1); + this.scan(pyLen(before) + pyLen(after) + beforePath.length + path.length + afterPath.length); + text = this.built(this.bounded([pyStrip(before), text, pyStrip(after)].filter(part => part).join(' '))); + path = [...beforePath, ...path, ...afterPath]; + } + } + } else if ((name === 'StringConcatenate' || name === 'Text Concatenate') && slot === 0 && kind === 'string') { + [text, path] = this.concatenate(name, inputs, depth); + storageText = text; + } else if (this.follows(name, slot, kind)) { + [text, path, storageText] = this.semantic(nodeId, name, slot, kind, inputs, depth); + } else { + throw this.unsupported('Unsupported node semantics or output slot', nodeId); + } + this.scan(path.length + 1); + path = [{ node_id: nodeId, output_slot: slot }, ...path]; + const pathLimit = this.maxDepth * Math.max(1, this.perCandidateVisits); + this.pathEntries -= path.length; + if (path.length > pathLimit || this.pathEntries < 0) throw new Unresolved('Provenance path limit reached', 'work-limit'); + const traced = [text, path, storageText]; + if (!this.tainted) { + this.memo.set(key, traced); + this.costs.set(key, allowance - this.budget.allowance); + this.heights.set(key, this.deepest - depth); + } + return traced; + } finally { + this.deepest = Math.max(outerDeepest, this.deepest); + this.tainted = outerTainted || this.tainted; + this.active.delete(key); + } + } + + /** `StringConcatenate` / `Text Concatenate` (the `text` branch). */ + concatenate(name, inputs, depth) { + let keys, delimiter, clean; + if (name === 'StringConcatenate') { + keys = ['string_a', 'string_b']; + delimiter = pyGet(inputs, 'delimiter', ''); + clean = false; + } else { + keys = [...inputs.keys()].filter(item => /^text_[a-z]$/.test(item)).sort(); + delimiter = pyGet(inputs, 'delimiter', ' '); + clean = pyStr(pyGet(inputs, 'clean_whitespace', 'true')).toLowerCase() === 'true'; + } + if (!keys.length || typeof delimiter !== 'string') throw new Unresolved('Malformed concatenation', 'malformed'); + const parts = [], path = []; + let size = 0; + for (const inputName of keys) { + let [part, followed] = this.text(pyGet(inputs, inputName, ''), 'string', depth + 1); + this.scan(pyLen(part) + followed.length); + if (clean) part = pyStrip(part); + path.push(...followed); + if (part || name === 'StringConcatenate') { + size += pyLen(part) + (parts.length ? pyLen(delimiter) : 0); + if (size > this.maxTextLength) throw new Unresolved('Resolved text exceeds the length limit', 'text-limit'); + parts.push(part); + } + } + return [this.built(parts.join(delimiter)), path]; + } + + /** `prompt_manager_*.py` at 07a5af3: strip, then join with ", ". */ + historical(adapted, inputs, depth) { + let [text, path] = this.text(pyGet(inputs, adapted.inputName, adapted.default), 'string', depth + 1); + this.scan(pyLen(text)); + text = pyStrip(text); + const storageText = text; + if (adapted.comma) { + let [before, beforePath] = this.text(pyGet(inputs, 'prepend_text') ?? '', 'string', depth + 1); + let [after, afterPath] = this.text(pyGet(inputs, 'append_text') ?? '', 'string', depth + 1); + this.scan(pyLen(before) + pyLen(after) + beforePath.length + afterPath.length); + before = pyStrip(before); after = pyStrip(after); + if (before) text = `${before}${text && !before.endsWith(',') ? ', ' : ''}${text}`; + if (after) text = `${text}${text && !text.endsWith(',') ? ', ' : ''}${after}`; + text = this.built(this.bounded(text)); + path = [...beforePath, ...path, ...afterPath]; + } + return [text, path, storageText]; + } + + follows(name, slot, kind) { + const semantics = this.semantics, key = slotKey(name, slot); + if (semantics.runtime.has(name)) return true; + if (semantics.encoders.has(key) || semantics.strings.has(key)) return true; + if (slot === 0 && semantics.selectors.has(name)) return true; + return kind === 'conditioning' && (semantics.conditioning.has(key) || (slot === 0 && semantics.composites.has(name))); + } + + semantic(nodeId, name, slot, kind, inputs, depth) { + const semantics = this.semantics, key = slotKey(name, slot); + if (semantics.runtime.has(name)) throw this.named(RUNTIME_REASON, 'runtime-value', nodeId); + for (const [table, expected, build] of [[semantics.encoders, 'conditioning', 'encoded'], [semantics.strings, 'string', 'stringed']]) { + const listed = table.get(key); + if (listed !== undefined) { + if (kind !== expected) throw new Unresolved(INCOMPATIBLE_SLOT, 'malformed'); + return this[build](nodeId, listed, inputs, depth); + } + } + const entry = kind === 'conditioning' ? semantics.conditioning.get(key) : undefined; + if (entry !== undefined && entry.strategy === 'zeroed') { + this.textSources.set(slotKey(nodeId, slot), ZEROED_SOURCE); + return ['', [], '']; + } + if (entry !== undefined) { + const traced = this.text(pyGet(inputs, entry.input), kind, depth + 1); + this.inheritSource(nodeId, slot, [traced[1]]); + return traced; + } + if (semantics.selectors.has(name)) return this.select(nodeId, semantics.selectors.get(name), inputs, kind, depth); + const parts = semantics.composites.get(name).inputs.map(inputName => this.text(pyGet(inputs, inputName), kind, depth + 1)); + if (new Set(parts.map(part => part[0])).size !== 1) throw this.named('Combined conditioning has different texts', 'composite', nodeId); + return this.merged(nodeId, slot, parts); + } + + select(nodeId, entry, inputs, kind, depth) { + const condition = pyGet(inputs, entry.condition), branches = entry.branches; + let choice; + if (typeof condition === 'boolean') choice = condition; + else if (!isLink(condition)) throw new Unresolved('Malformed selector condition', 'malformed'); + else if (this.choices.has(slotKey(String(condition[0]), condition[1]))) { + choice = this.choices.get(slotKey(String(condition[0]), condition[1])); + this.tainted = true; + } else choice = null; + if (choice !== null) { + const traced = this.text(pyGet(inputs, branches[choice ? 'true' : 'false']), kind, depth + 1); + this.inheritSource(nodeId, 0, [traced[1]]); + return traced; + } + const parts = ['true', 'false'].map(label => this.text(pyGet(inputs, branches[label]), kind, depth + 1)); + if (parts[0][0] !== parts[1][0]) throw new Diverging(slotKey(String(condition[0]), condition[1])); + return this.merged(nodeId, 0, parts); + } + + merged(nodeId, slot, parts) { + const traced = this.joinedPaths(parts, parts); + this.inheritSource(nodeId, slot, parts.map(part => part[1])); + return traced; + } + + joinedPaths(chosen, parts) { + const text = chosen[0][0]; + const storages = new Set(chosen.map(part => part[2])); + const storageText = storages.size === 1 ? chosen[0][2] : text; + const paths = parts.map(part => part[1]); + this.scan(paths.reduce((sum, path) => sum + path.length, 0)); + const merged = [], seen = new Set(); + for (const path of paths) { + for (const step of path) { + const identity = slotKey(step.node_id, step.output_slot); + if (!seen.has(identity)) { seen.add(identity); merged.push(step); } + } + } + return [text, merged, storageText]; + } + + encoded(nodeId, entry, inputs, depth) { + const names = entry.inputs; + if (entry.strategy === 'single') return this.text(pyGet(inputs, names[0]), 'string', depth + 1); + if (entry.strategy === 'flag-parts') return this.flagged(nodeId, entry, inputs, depth); + if (entry.strategy !== 'parts-equal') throw this.unsupported('Unsupported encoder strategy', nodeId); + const parts = names.map(name => this.text(pyGet(inputs, name), 'string', depth + 1)); + this.scan(parts.reduce((sum, part) => sum + pyLen(part[0]), 0)); + if (new Set(parts.map(part => part[0])).size === 1) return this.joinedPaths(parts, parts); + const filled = parts.filter(part => part[0] !== ''); + if (filled.length === 1) return this.joinedPaths(filled, parts); + throw this.named('Encoder parts have different texts', 'composite', nodeId); + } + + flagged(nodeId, entry, inputs, depth) { + const names = entry.inputs; + if (!this.setting(nodeId, inputs, entry.params.flag, 'bool')) return this.text(pyGet(inputs, names[0]), 'string', depth + 1); + const parts = names.map(name => this.text(pyGet(inputs, name), 'string', depth + 1)); + this.scan(parts.reduce((sum, part) => sum + pyLen(part[0]), 0)); + if (new Set(parts.map(part => part[0])).size === 1) return this.joinedPaths(parts, parts); + throw this.named(RUNTIME_REASON, 'runtime-value', nodeId); + } + + stringed(nodeId, entry, inputs, depth) { + const strategy = entry.strategy, source = entry.inputs[0]; + if (strategy === 'literal') return this.text(pyGet(inputs, source), 'string', depth + 1); + if (strategy === 'strip-newlines') { + const flag = this.setting(nodeId, inputs, entry.params.flag, 'bool'); + const traced = this.text(pyGet(inputs, source), 'string', depth + 1); + if (!flag) return traced; + this.scan(pyLen(traced[0])); + const text = this.built(this.bounded(pyStrip(traced[0].replaceAll('\n', '')))); + return [text, traced[1], text]; + } + if (strategy === 'join-multi') return this.joinMulti(nodeId, entry, inputs, depth); + throw this.unsupported('Unsupported string strategy', nodeId); + } + + /** A literal node setting of exactly `type(value) is kind`; linked is `unsupported-node`, else malformed. */ + setting(nodeId, inputs, name, kind) { + if (!inputs.has(name)) throw new Unresolved('Missing string node setting', 'malformed'); + const value = inputs.get(name); + if (isLink(value)) throw this.unsupported('Linked string node setting', nodeId); + const typed = { bool: typeof value === 'boolean', int: isInt(value), str: typeof value === 'string' }[kind]; + if (!typed) throw new Unresolved('Malformed string node setting', 'malformed'); + return value; + } + + joinMulti(nodeId, entry, inputs, depth) { + const params = entry.params, flag = params.list_flag; + if (!inputs.has(flag)) throw new Unresolved('Missing string node setting', 'malformed'); + if (isLink(inputs.get(flag)) || inputs.get(flag) === true) throw this.named(RUNTIME_REASON, 'runtime-value', nodeId); + if (inputs.get(flag) !== false) throw new Unresolved('Malformed string node setting', 'malformed'); + const count = this.setting(nodeId, inputs, params.count, 'int'); + const delimiter = this.setting(nodeId, inputs, params.delimiter, 'str'); + if (!(count >= 1 && count <= MAX_JOIN_INPUTS)) throw new Unresolved('Malformed string node setting', 'malformed'); + const total = Number(count); + this.scan(total); + const names = [entry.inputs[0]]; + for (let index = 2; index <= total; index++) names.push(`${params.input_prefix}${index}`); + const parts = [], path = [], seen = new Set(); + let size = 0; + names.forEach((inputName, position) => { + if (position && !inputs.has(inputName)) return; + const [part, followed] = this.text(pyGet(inputs, inputName), 'string', depth + 1); + this.scan(pyLen(part) + followed.length); + for (const step of followed) { + const identity = slotKey(step.node_id, step.output_slot); + if (!seen.has(identity)) { seen.add(identity); path.push(step); } + } + if (position && !part) return; + size += pyLen(part) + (parts.length ? pyLen(delimiter) : 0); + if (size > this.maxTextLength) throw new Unresolved('Resolved text exceeds the length limit', 'text-limit'); + parts.push(part); + }); + const text = this.built(parts.join(delimiter)); + return [text, path, text]; + } + + sourceOf(path) { + if (!path.length) return 'graph-inferred'; + return this.textSources.get(slotKey(path[0].node_id, path[0].output_slot)) ?? 'graph-inferred'; + } + inheritSource(nodeId, slot, paths) { + const sources = new Set(paths.map(path => this.sourceOf(path))); + if (sources.size === 1) this.textSources.set(slotKey(nodeId, slot), [...sources][0]); + else this.textSources.delete(slotKey(nodeId, slot)); + } + unverifiable(error) { return UNVERIFIABLE_CODES.has(error.code); } + + executionRecord(nodeId, inputs) { + const record = readPairExecution(this.metadata, nodeId); + if (record === null) return null; + for (const name of ['text', 'negative_text', 'prepend_text', 'append_text']) { + let expected; + try { + expected = this.text(pyGet(inputs, name, ''), 'string')[0]; + } catch (error) { + if (error instanceof Unresolved && this.unverifiable(error)) { + const value = pyGet(inputs, name); + if (isLink(value)) { + const [sourceName] = this.node(String(value[0])); + const known = ADAPTER_SLOTS.get(sourceName); + if (known && !known.has(String(value[1]))) throw error; + if (['StringConcatenate', 'Text Concatenate', 'Reroute'].includes(sourceName) && value[1] !== 0) throw error; + } + continue; + } + throw error; + } + if (name === 'prepend_text' || name === 'append_text') expected = pyStrip(expected); + if (expected !== record[name]) throw new Unresolved('Execution evidence does not match recorded node inputs', 'malformed'); + } + return record; + } + + side(value, samplerId, guiderId = null, depth = 0) { + const [text, path, storageText] = this.text(value, 'conditioning', depth); + const origin = path[0]; + const provenance = { + format: 'comfyui', sampler_id: samplerId, ...origin, path, + text_source: this.textSources.get(slotKey(origin.node_id, origin.output_slot)) ?? 'graph-inferred', + }; + if (guiderId !== null) provenance.guider_id = guiderId; + return { text, storage_text: storageText, provenance }; + } + + guider(value) { + const seen = new Set(); + let depth = 0; + for (;;) { + if (depth >= this.maxDepth) throw new Unresolved('Resolution depth limit reached', 'depth-limit'); + if (!isLink(value)) throw new Unresolved('Expected a guider link', 'malformed'); + const nodeId = String(value[0]), slot = value[1]; + if (seen.has(nodeId)) throw new Unresolved('Cyclic guider ancestry', 'malformed'); + seen.add(nodeId); + this.budget.spend(); + const [name, inputs] = this.node(nodeId); + this.scan(inputs.size); + depth += 1; + if (name === 'Reroute' && slot === 0) { + const keys = ['value', 'input', 'in'].filter(item => inputs.has(item)); + if (keys.length !== 1) throw new Unresolved('Reroute input is not uniquely identifiable', 'malformed'); + value = inputs.get(keys[0]); + continue; + } + const entry = this.semantics.guiders.get(name); + if (entry === undefined || slot !== 0) throw this.unsupported('Unsupported guider', nodeId); + return [nodeId, inputs, { positive: entry.positive, negative: entry.negative ?? null }, entry.absent_reason ?? GUIDER_ABSENT_REASON, depth]; + } + } + + pair(samplerId) { + this.budget.reset(this.perCandidateVisits); + this.latentCharged = new Set(); + if (this.budget.total <= 0) return result('unresolved', { samplerId, reason: 'Resolution visit limit reached', reasonCode: 'work-limit' }); + return this.branches(samplerId); + } + + branches(samplerId) { + const pending = [new Map()], results = []; + try { + while (pending.length) { + this.choices = pending.shift(); + try { + results.push(stage(this, samplerId, new Set())); + } catch (error) { + if (!(error instanceof Diverging)) throw error; + if (results.length + pending.length + 2 > MAX_BRANCH_CANDIDATES) throw new Unresolved('Too many selector branches', 'work-limit'); + for (const choice of [true, false]) pending.push(new Map([...this.choices, [error.key, choice]])); + } + } + } catch (error) { + if (!(error instanceof Unresolved)) throw error; + return result('unresolved', { samplerId, reason: error.message, reasonCode: error.code, node: error.node }); + } finally { + this.choices = new Map(); + } + if (results.every(item => item.state === 'unresolved')) return results[0]; + if (new Set(results.map(outcomeKey)).size === 1) return results[0]; + return result('ambiguous', { samplerId, reason: 'Selector branches have different prompts', candidates: results }); + } + + sides(samplerId) { + let positive = null, negative = null; + try { + let [name, inputs] = this.node(samplerId); + const entry = this.semantics.samplers.get(name); + this.checkOverrides(samplerId, entry, inputs); + const latent = entry.latent; + if (latent !== undefined && latent !== null && inputs.has(latent)) this.latentChecked(samplerId, inputs.get(latent)); + let guiderId = null, depth = 0, conditioning = entry.conditioning, absentReason = 'Negative input is absent'; + if (entry.strategy === 'custom-advanced') { + let guiderReason; + [guiderId, inputs, conditioning, guiderReason, depth] = this.guider(pyGet(inputs, conditioning.guider)); + if (conditioning.negative === null) absentReason = guiderReason; + } + positive = this.side(pyGet(inputs, conditioning.positive), samplerId, guiderId, depth); + if (!pyStrip(positive.text)) throw new Unresolved(EMPTY_POSITIVE_REASON); + const negativeName = conditioning.negative; + if (negativeName === null || negativeName === undefined || !inputs.has(negativeName)) { + return result('absent', { positive, samplerId, reason: absentReason }); + } + negative = this.side(inputs.get(negativeName), samplerId, guiderId, depth); + return result('resolved', { positive, negative, samplerId }); + } catch (error) { + if (!(error instanceof Unresolved)) throw error; + return result('unresolved', { positive, negative, samplerId, reason: error.message, reasonCode: error.code, node: error.node }); + } + } + + checkOverrides(samplerId, entry, inputs) { + for (const name of entry.prompt_overrides ?? []) { + const value = pyGet(inputs, name); + if (value === null || value === '') continue; + if (isLink(value)) throw this.unsupported('Unsupported prompt override', String(value[0])); + throw this.named(RUNTIME_REASON, 'runtime-value', samplerId); + } + } + + latentChecked(samplerId, value) { + let error; + if (this.latentWalks.has(samplerId)) { + const [walked, cost] = this.latentWalks.get(samplerId); + error = walked; + if (!this.latentCharged.has(samplerId)) { + this.budget.charge(cost); + this.latentCharged.add(samplerId); + } + } else { + const before = this.budget.allowance; + try { + this.latentStages(samplerId, value); + error = null; + } catch (raised) { + if (!(raised instanceof Unresolved) || raised.code === 'work-limit') throw raised; + error = raised; + } + this.latentWalks.set(samplerId, [error, before - this.budget.allowance]); + this.latentCharged.add(samplerId); + } + if (error !== null) throw new Unresolved(error.message, error.code, error.node === null ? null : { ...error.node }); + } + + enqueue(queue, queued, inputs, depth) { + this.scan(inputs.size); + for (const item of inputs.values()) { + if (!isLink(item)) continue; + const key = String(item[0]); + if (!queued.has(key)) { queued.add(key); queue.push([key, depth]); } + } + } + + stageShaped(name, inputs) { + if (this.semantics.allClasses.has(name)) return false; + const { shaped, withModel } = this.semantics.stageInputs; + if (shaped.some(key => isLink(pyGet(inputs, key)))) return true; + return isLink(pyGet(inputs, 'model')) && withModel.some(key => isLink(pyGet(inputs, key))); + } + + latentStages(origin, value) { + if (!isLink(value)) throw new Unresolved('Unknown latent ancestry', 'malformed'); + const start = String(value[0]), queue = [[start, 0]], queued = new Set([start]); + for (let head = 0; head < queue.length; head++) { + const [nodeId, depth] = queue[head]; + if (nodeId === origin) throw new Unresolved('Cyclic latent ancestry', 'malformed'); + if (depth >= this.maxDepth) throw new Unresolved('Resolution depth limit reached', 'depth-limit'); + this.budget.spend(); + const [name, inputs] = this.node(nodeId); + if (this.stageClasses.has(name)) throw new Unresolved(MULTISTAGE_UNATTRIBUTED_REASON); + if (this.stageShaped(name, inputs)) throw this.unsupported('Unsupported latent ancestry', nodeId); + this.enqueue(queue, queued, inputs, depth + 1); + } + } +} + + +/** `_sampler_like_classes`: distinct classes, in graph order, of nodes shaped like samplers or guiders. */ +function samplerLikeClasses(graph) { + const names = []; + for (const node of graph.values()) { + if (!isDict(node) || !isDict(pyGet(node, 'inputs'))) continue; + const name = pyGet(node, 'class_type'); + if (typeof name !== 'string' || !name || names.includes(name)) continue; + if (SAMPLER_LIKE_INPUTS.some(key => isLink(pyGet(node.get('inputs'), key)))) { + names.push(pySlice(name, CLASS_NAME_LENGTH)); + if (names.length === NO_SAMPLER_NAMES) break; + } + } + return names; +} + +function noSampler(graph) { + const seen = samplerLikeClasses(graph); + const reason = `No supported sampler pair found${seen.length ? ` (saw ${seen.join(', ')})` : ''}`; + return result('unresolved', { reason, reasonCode: 'no-sampler' }); +} + +/** `_prompt_manager_widgets`: API node ID to widget text for every PromptManager node that runs. */ +function promptManagerWidgets(workflow) { + const nodes = isDict(workflow) ? pyGet(workflow, 'nodes') : null; + if (!isList(nodes)) return new Map(); + const definitions = pyGet(workflow, 'definitions'); + const listed = isDict(definitions) ? pyGet(definitions, 'subgraphs') : null; + const subgraphs = new Map(); + for (const subgraph of isList(listed) ? listed : []) { + if (isDict(subgraph) && typeof pyGet(subgraph, 'id') === 'string' && isList(pyGet(subgraph, 'nodes'))) subgraphs.set(subgraph.get('id'), subgraph.get('nodes')); + } + const widgets = new Map(), stack = [[nodes, '', 0]]; + let visited = 0; + while (stack.length) { + const [members, prefix, depth] = stack.pop(); + for (const node of members) { + visited += 1; + if (visited > MAX_WORKFLOW_NODES) return widgets; + if (!isDict(node)) continue; + const kind = pyGet(node, 'type'), nodeId = pyGet(node, 'id'); + if (!(typeof nodeId === 'string' || isInt(nodeId))) continue; + const apiId = `${prefix}${String(nodeId)}`; + // A list or object `type` is neither a subgraph instance nor a PromptManager node (#286). + if (isList(kind) || isDict(kind)) continue; + if (typeof kind === 'string' && subgraphs.has(kind) && depth < MAX_SUBGRAPH_DEPTH) { + stack.push([subgraphs.get(kind), `${apiId}:`, depth + 1]); + continue; + } + const values = pyGet(node, 'widgets_values'); + const text = isList(values) && values.length && typeof values[0] === 'string' ? values[0] : + isDict(values) && typeof pyGet(values, 'text') === 'string' ? values.get('text') : null; + if (typeof kind === 'string' && kind !== 'PromptManagerPair' && kind.toLowerCase().includes('promptmanager') && text !== null) widgets.set(apiId, text); + } + } + return widgets; +} + +/** `_overwritten_prompt_nodes` (R1). */ +function overwrittenPromptNodes(workflow, graph) { + const widgets = promptManagerWidgets(workflow), byText = new Map(); + for (const [nodeId] of widgets) { + const node = pyGet(graph, nodeId); + const inputs = isDict(node) ? pyGet(node, 'inputs') : null; + const text = isDict(inputs) ? pyGet(inputs, 'text') : null; + if (typeof text === 'string') { + if (!byText.has(text)) byText.set(text, []); + byText.get(text).push(nodeId); + } + } + const found = new Set(); + for (const ids of byText.values()) { + if (ids.length > 1 && new Set(ids.map(id => widgets.get(id))).size > 1) ids.forEach(id => found.add(id)); + } + return found; +} + +/** `_resolve` for an unanchored inspection (output_node_id None). */ +function resolve(metadata, semantics) { + if (!isDict(metadata) || !metadata.size) return result('absent', { reason: 'No parsed prompt metadata' }); + let graph; + if (metadata.has('prompt')) graph = metadata.get('prompt'); + else if (metadata.has('parameters')) return parameters(metadata.get('parameters'), PROFILE.maxTextLength); + else graph = metadata; + if (!isDict(graph) || !graph.size) return result('unresolved', { reason: 'API graph is missing or malformed', reasonCode: 'malformed' }); + if (graph.size > PROFILE.nodeCeiling) return result('unresolved', { reason: 'Prompt graph exceeds the inspection node ceiling', reasonCode: 'graph-ceiling' }); + if (semantics === null) return result('unresolved', { reason: SEMANTICS_UNAVAILABLE_REASON }); + let overwritten = new Set(); + if (metadata.has('prompt')) { + overwritten = overwrittenPromptNodes(pyGet(metadata, 'workflow'), graph); + } + const resolver = new GraphResolver(graph, metadata.has('prompt') ? metadata : null, semantics, overwritten); + const samplerIds = finalStages(resolver, [...graph].filter(([, node]) => isDict(node) && typeof pyGet(node, 'class_type') === 'string' && + resolver.samplerClasses.has(node.get('class_type'))).map(([id]) => id)); + if (!samplerIds.length) return noSampler(graph); + if (samplerIds.length > 1) { + const candidates = samplerIds.map(id => resolver.pair(id)); + return sharedPair(candidates) ?? result('ambiguous', { reason: 'Multiple sampler branches', candidates }); + } + return resolver.pair(samplerIds[0]); +} + + +/** `_may_hold_prompt_manager`. */ +function mayHoldPromptManager(canonical) { + const graph = pyGet(canonical, 'prompt'); + if (!isDict(graph)) return false; + for (const node of graph.values()) { + if (!isDict(node)) continue; + const name = pyGet(node, 'class_type'), inputs = pyGet(node, 'inputs'); + if (typeof name === 'string' && name.toLowerCase().includes('promptmanager')) return true; + if (isDict(inputs) && inputs.has('search_text')) return true; + } + return false; +} + +/** `_parsed_workflow`: the UI workflow as a dict, or null. */ +function parsedWorkflow(value) { + if (typeof value === 'string') { + try { value = pyJsonLoads(value); } catch (error) { + if (error instanceof PyValueError) return null; + throw error; + } + } + return isDict(value) ? value : null; +} + +/** `unreadable_evidence`: both roles when the file's metadata could not be read at all. */ +export function unreadableEvidence() { + const resolution = { state: 'unresolved', sampler_id: null, reason: UNREADABLE_METADATA_REASON, reason_code: null, node: null }; + return { prompts: explained({ positive: sideOf('unresolved'), negative: sideOf('unresolved') }, resolution), resolution }; +} + +/** + * `inspect_prompt_evidence(records, None, profile=INSPECTION_PROFILE)`: `{prompts, resolution}` for the records a + * local read found (`{prompt, workflow, parameters, comfyassets_prompt_pairs}` texts). `semantics` is + * `compileSemantics(...)`'s table, or null when it could not be loaded. + */ +export function resolveLocalEvidence(records, semantics) { + const source = records !== null && typeof records === 'object' ? records : {}; + const metadata = new Map(Object.entries(source).filter(([key]) => ROLE_METADATA_KEYS.has(key))); + const malformedResolution = { state: 'unresolved', sampler_id: null, reason: MALFORMED_EVIDENCE_REASON, reason_code: 'malformed', node: null }; + if (!metadata.size) { + return { + prompts: { positive: sideOf('absent'), negative: sideOf('absent') }, + resolution: { state: 'absent', sampler_id: null, reason: 'No parsed prompt metadata', reason_code: null, node: null }, + }; + } + const malformed = { prompts: explained({ positive: sideOf('unresolved'), negative: sideOf('unresolved') }, malformedResolution), resolution: malformedResolution }; + if (!metadata.has('prompt') && !metadata.has('parameters')) return malformed; + if (typeof metadata.get('prompt') === 'string') { + try { metadata.set('prompt', pyJsonLoads(metadata.get('prompt'))); } catch (error) { + if (error instanceof PyValueError) return malformed; + throw error; + } + } + const workflow = mayHoldPromptManager(metadata) ? parsedWorkflow(source.workflow ?? null) : null; + if (workflow !== null && metadata.has('prompt')) metadata.set('workflow', workflow); + const resolved = resolve(metadata, semantics); + const state = resolved.state, prompts = {}; + for (const role of ['positive', 'negative']) { + const side = resolved[role]; + const present = side !== null && typeof side === 'object'; + if (state !== 'ambiguous' && present && (role === 'negative' || pyStrip(side.text))) prompts[role] = sideOf('resolved', side.text, side.provenance.text_source); + else if (state === 'resolved' && present) prompts[role] = { ...sideOf('unresolved'), message: EMPTY_POSITIVE }; + else prompts[role] = sideOf(state !== 'resolved' ? state : 'unresolved'); + } + const resolution = { state, sampler_id: resolved.sampler_id, reason: resolved.reason, reason_code: resolved.reason_code, node: resolved.node }; + return { prompts: explained(prompts, resolution), resolution }; +} + diff --git a/web/js/workspace/local-semantics.mjs b/web/js/workspace/local-semantics.mjs new file mode 100644 index 0000000..bfda05d --- /dev/null +++ b/web/js/workspace/local-semantics.mjs @@ -0,0 +1,27 @@ +// The node table local Inspect resolves with (#249 local Inspect, PR L3 Task 10): web/js/inspection-semantics.json, +// the very table the server's inspector reads, fetched once per page through the API client (the proxy-mount rule). +// The Inspect page asks for it as it mounts, before any file is chosen; it is the only static file Inspect fetches, +// and the request carries nothing about a selection. A table that cannot be fetched or used is null: the roles then +// answer as the server does when its table is unusable, and a later selection asks again. +import { compileSemantics } from './local-resolver.mjs'; + +export const SEMANTICS_PATH = '/prompt_manager/js/inspection-semantics.json'; +let pending = null; + +async function fetchSemantics() { + const client = globalThis.window?.ApiClient; + if (typeof client?.resolveUrl !== 'function' || typeof globalThis.fetch !== 'function') return null; + const response = await globalThis.fetch(client.resolveUrl(SEMANTICS_PATH), { credentials: 'same-origin' }); + if (!response.ok) throw new Error(`Inspection node table request failed (${response.status})`); + return compileSemantics(await response.json()); +} + +/** The compiled table (one request per page), or null when it is unavailable. */ +export function loadInspectionSemantics() { + if (pending !== null) return pending; + const current = pending = fetchSemantics().catch(() => null).then(table => { + if (table === null && pending === current) pending = null; + return table; + }); + return current; +} diff --git a/web/js/workspace/local-video.mjs b/web/js/workspace/local-video.mjs index f414cd5..0cc26e4 100644 --- a/web/js/workspace/local-video.mjs +++ b/web/js/workspace/local-video.mjs @@ -17,6 +17,7 @@ // server folds them. import { INT_MAX_STR_DIGITS } from "./local-projection.mjs"; +import { JSON_MAX_DEPTH } from "./py-json.mjs"; // Role records (prompt, parameters, the pair execution record) share one budget: // past it the read fails. A workflow has its own budget; past it only the workflow @@ -40,7 +41,6 @@ const MAX_NAME_BYTES = 64; // the longest carrier name is 24 bytes; longer names export const VIDEO_READ_CEILING = MAX_VIDEO_ELEMENTS * (MAX_HEADER_BYTES + MAX_NAME_BYTES) + VIDEO_TAG_READ_BYTES; const PREFIX_BYTES = 32; const YIELD_INTERVAL_MS = 8; -const JSON_MAX_DEPTH = 1000; // Python's default recursion limit const ROLE_KEYS = ["prompt", "parameters", "comfyassets_prompt_pairs"]; const METADATA_KEYS = ["prompt", "workflow", "parameters", "comfyassets_prompt_pairs"]; @@ -826,8 +826,9 @@ export function pythonJsonLoads(text) { } } function value(depth) { - if (depth > JSON_MAX_DEPTH) throw new PythonJsonError("Maximum recursion depth exceeded", true); const char = text[pos]; + // The shared cap (py-json.mjs): `depth` containers enclose this value, and it would be one more. + if ((char === "{" || char === "[") && depth >= JSON_MAX_DEPTH) throw new PythonJsonError("Maximum recursion depth exceeded", true); if (char === '"') return string(); if (char === "{") { pos += 1; diff --git a/web/js/workspace/py-json.mjs b/web/js/workspace/py-json.mjs new file mode 100644 index 0000000..5c87291 --- /dev/null +++ b/web/js/workspace/py-json.mjs @@ -0,0 +1,249 @@ +// Python's value model for the local inspection resolver (#249 local Inspect, PR L3): the server's resolver +// (utils/prompt_pair_resolver.py) runs on `json.loads` output, so the browser port reads the same text the same way. +// Objects are `Map`s (insertion order, a repeated key keeps its first position and its last value, as a dict does), +// integers are numbers (or BigInt past 2^53 - 1), floats are `PyFloat`, None is null. Strings are measured, sliced and +// stripped as Python's `str` is: by code point, with `str.isspace()` whitespace. No DOM. + +/** A Python float: distinct from an int (`1.0` is not a link slot, `type(x) is int` is false). */ +export class PyFloat { + constructor(value) { + this.value = value; + Object.freeze(this); + } +} + +/** `ValueError` from `json.loads` (malformed text, or an integer past `sys.int_info.str_digits_check_threshold`). */ +export class PyValueError extends Error { + constructor(message) { + super(message); + this.name = 'PyValueError'; + } +} + +// CPython's default int max str digits (PEP 651 / gh-95778). +const INT_MAX_STR_DIGITS = 4300; +/** + * The nesting both browser CPython-JSON parsers accept (this one and local-video.mjs's): every array or object counts, + * an empty one too, as CPython's scanner enters a recursion level for each. Past it `json.loads` raises RecursionError, + * which the server treats as invalid JSON; its real limit depends on the Python (TESTING.md, "Deep JSON"). + */ +export const JSON_MAX_DEPTH = 1000; +const MAX_SAFE_DIGITS = '9007199254740991'; +const NUMBER = /-?(?:0|[1-9][0-9]*)(\.[0-9]+)?([eE][-+]?[0-9]+)?/y; +const STRING_STOP = /["\\\u0000-\u001f]/g; +const HEX4 = /^[0-9a-fA-F]{4}$/; +const ESCAPES = { '"': '"', '\\': '\\', '/': '/', b: '\b', f: '\f', n: '\n', r: '\r', t: '\t' }; +// The C scanner's constants, in its order of checks. +const CONSTANTS = [['null', null], ['true', true], ['false', false], ['NaN', new PyFloat(NaN)], + ['Infinity', new PyFloat(Infinity)], ['-Infinity', new PyFloat(-Infinity)]]; + +export const isDict = value => value instanceof Map; +export const isList = value => Array.isArray(value); +/** `isinstance(value, int) and not isinstance(value, bool)`. */ +export const isInt = value => (typeof value === 'number' && Number.isInteger(value)) || typeof value === 'bigint'; + +function numberValue(match) { + const [literal, fraction, exponent] = match; + if (fraction || exponent) return new PyFloat(Number(literal)); + const digits = literal[0] === '-' ? literal.slice(1) : literal; + if (digits.length > INT_MAX_STR_DIGITS) throw new PyValueError('Exceeds the limit for integer string conversion'); + if (digits.length > MAX_SAFE_DIGITS.length || (digits.length === MAX_SAFE_DIGITS.length && digits > MAX_SAFE_DIGITS)) return BigInt(literal); + // `-0` is the int 0. + return Number(literal) || 0; +} + +/** `json.loads(text)` with Python's defaults (C scanner): NaN/Infinity accepted, a repeated key's last value wins. */ +export function pyJsonLoads(text) { + if (typeof text !== 'string') throw new TypeError('JSON text must be a string'); + if (text.startsWith('')) throw new PyValueError('Unexpected UTF-8 BOM (decode using utf-8-sig)'); + let pos = 0; + const fail = message => new PyValueError(`${message}: char ${pos}`); + const skip = () => { + while (pos < text.length) { + const c = text.charCodeAt(pos); + if (c !== 0x20 && c !== 0x09 && c !== 0x0a && c !== 0x0d) break; + pos++; + } + }; + function string() { + pos++; + let out = ''; + for (;;) { + STRING_STOP.lastIndex = pos; + const stop = STRING_STOP.exec(text); + if (!stop) throw fail('Unterminated string starting at'); + out += text.slice(pos, stop.index); + pos = stop.index + 1; + if (stop[0] === '"') return out; + if (stop[0] !== '\\') throw fail('Invalid control character at'); + const escape = text[pos]; + if (escape === 'u') { + const hex = text.slice(pos + 1, pos + 5); + if (!HEX4.test(hex)) throw fail('Invalid \\uXXXX escape'); + pos += 5; + const code = parseInt(hex, 16); + if (code >= 0xd800 && code <= 0xdbff && text[pos] === '\\' && text[pos + 1] === 'u') { + const low = text.slice(pos + 2, pos + 6); + if (!HEX4.test(low)) throw fail('Invalid \\uXXXX escape'); + const lowCode = parseInt(low, 16); + if (lowCode >= 0xdc00 && lowCode <= 0xdfff) { + out += String.fromCharCode(code, lowCode); + pos += 6; + continue; + } + } + out += String.fromCharCode(code); + } else if (Object.hasOwn(ESCAPES, escape)) { + out += ESCAPES[escape]; + pos++; + } else throw fail('Invalid \\escape'); + } + } + function key() { + if (text[pos] !== '"') throw fail('Expecting property name enclosed in double quotes'); + const name = string(); + skip(); + if (text[pos] !== ':') throw fail("Expecting ':' delimiter"); + pos++; + skip(); + return name; + } + function scalar() { + if (text[pos] === '"') return string(); + for (const [literal, value] of CONSTANTS) { + if (text.startsWith(literal, pos)) { + pos += literal.length; + return value; + } + } + NUMBER.lastIndex = pos; + const match = NUMBER.exec(text); + if (!match) throw fail('Expecting value'); + pos += match[0].length; + return numberValue(match); + } + skip(); + const stack = []; + const enter = () => { + if (stack.length >= JSON_MAX_DEPTH) throw fail('Maximum JSON nesting depth exceeded'); + pos++; skip(); + }; + let result; + for (;;) { + let value; + if (text[pos] === '{') { + enter(); + const frame = { value: new Map(), object: true, key: null }; + if (text[pos] === '}') pos++; + else { frame.key = key(); stack.push(frame); continue; } + value = frame.value; + } else if (text[pos] === '[') { + enter(); + const frame = { value: [], object: false }; + if (text[pos] === ']') pos++; + else { stack.push(frame); continue; } + value = frame.value; + } else value = scalar(); + for (;;) { + if (!stack.length) { result = value; break; } + const frame = stack[stack.length - 1]; + if (frame.object) frame.value.set(frame.key, value); + else frame.value.push(value); + skip(); + if (text[pos] === ',') { + pos++; skip(); + if (frame.object) frame.key = key(); + break; + } + if (text[pos] !== (frame.object ? '}' : ']')) throw fail("Expecting ',' delimiter"); + pos++; + stack.pop(); + value = frame.value; + } + if (!stack.length) break; + } + skip(); + if (pos !== text.length) throw fail('Extra data'); + return result; +} + +/** `len(text)`: code points (a lone surrogate counts once). */ +export function pyLen(text) { + let pairs = 0; + for (let index = 0; index < text.length - 1; index++) { + const code = text.charCodeAt(index); + if (code >= 0xd800 && code <= 0xdbff) { + const next = text.charCodeAt(index + 1); + if (next >= 0xdc00 && next <= 0xdfff) { pairs++; index++; } + } + } + return text.length - pairs; +} + +/** `text[:count]` by code points. */ +export function pySlice(text, count) { + if (text.length <= count) return text; + let end = 0; + for (let taken = 0; taken < count && end < text.length; taken++) { + const code = text.charCodeAt(end); + const next = text.charCodeAt(end + 1); + end += code >= 0xd800 && code <= 0xdbff && next >= 0xdc00 && next <= 0xdfff ? 2 : 1; + } + return text.slice(0, end); +} + +// `str.isspace()`: Unicode Zs plus the bidi classes B, S and WS (not U+FEFF, unlike `trim()`). +export const PY_SPACE = '\\t\\n\\x0b\\x0c\\r\\x1c-\\x1f \\x85\\xa0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000'; +const LEADING = new RegExp(`^[${PY_SPACE}]+`), TRAILING = new RegExp(`[${PY_SPACE}]+$`); +/** `text.strip()`. */ +export const pyStrip = text => text.replace(LEADING, '').replace(TRAILING, ''); + +/** `bool(value)`. */ +export function pyTruthy(value) { + if (value === null || value === undefined || value === false) return false; + if (value === true) return true; + if (typeof value === 'number') return value !== 0; + if (typeof value === 'bigint') return value !== 0n; + if (value instanceof PyFloat) return value.value !== 0; + if (typeof value === 'string' || isList(value)) return value.length > 0; + if (isDict(value)) return value.size > 0; + return true; +} + +/** `value == 1` (True and 1.0 equal it too). */ +export const pyEqualsOne = value => value === 1 || value === 1n || value === true || (value instanceof PyFloat && value.value === 1); + +/** `repr(float)`: the shortest round-trip digits, fixed for exponents -4..15, else `d.ddde+XX`. */ +export function pyFloatRepr(value) { + if (Number.isNaN(value)) return 'nan'; + if (!Number.isFinite(value)) return value > 0 ? 'inf' : '-inf'; + if (value === 0) return Object.is(value, -0) ? '-0.0' : '0.0'; + const [mantissa, exponentText] = value.toExponential().split('e'); + const exponent = Number(exponentText); + const sign = mantissa.startsWith('-') ? '-' : ''; + const digits = mantissa.replace(/^-/, '').replace('.', ''); + if (exponent < -4 || exponent >= 16) { + const rest = digits.slice(1); + return `${sign}${digits[0]}${rest ? `.${rest}` : ''}e${exponent < 0 ? '-' : '+'}${String(Math.abs(exponent)).padStart(2, '0')}`; + } + if (exponent < 0) return `${sign}0.${'0'.repeat(-exponent - 1)}${digits}`; + const whole = digits.slice(0, exponent + 1).padEnd(exponent + 1, '0'), fraction = digits.slice(exponent + 1); + return `${sign}${whole}.${fraction || '0'}`; +} + +/** + * `str(value)` where the resolver compares the result with node class names (`str(node.get("class_type", ""))`). + * A container's text never equals a class name, so it is a marker only. + */ +export function pyStr(value) { + if (typeof value === 'string') return value; + if (value === null || value === undefined) return 'None'; + if (value === true) return 'True'; + if (value === false) return 'False'; + if (typeof value === 'number' || typeof value === 'bigint') return String(value); + if (value instanceof PyFloat) return pyFloatRepr(value.value); + return '\u0000container'; +} + +/** `mapping.get(key, fallback)`. */ +export const pyGet = (mapping, key, fallback = null) => mapping.has(key) ? mapping.get(key) : fallback; diff --git a/web/js/workspace/workspace-dialogs.mjs b/web/js/workspace/workspace-dialogs.mjs index bdfa84f..39b35e6 100644 --- a/web/js/workspace/workspace-dialogs.mjs +++ b/web/js/workspace/workspace-dialogs.mjs @@ -286,14 +286,17 @@ export function openImportDialog({ scope, onInspect, onRescan, onMetadataScan = return { setRescanBusy }; } -/** "Copy prompt": the text in a readonly, pre-selected textarea for a manual copy. */ -export function openCopyFallback(text, { scope, trigger = null } = {}) { +/** + * "Copy prompt": the text in a readonly, pre-selected textarea for a manual copy. `title` names another copy's dialog + * (D117 "Copy settings summary"). + */ +export function openCopyFallback(text, { scope, trigger = null, title = 'Copy prompt' } = {}) { requireScope(scope); if (typeof text !== 'string') throw new TypeError('Copy text must be a string'); const area = el('textarea'); area.readOnly = true; area.value = text; - show('Copy prompt', [ + show(title, [ field('Select and copy this text', area, 'copy-text'), el('p', 'Automatic clipboard access requires a secure browser context.', 'small'), ], { scope, trigger, focusTarget: area }); diff --git a/web/js/workspace/workspace.css b/web/js/workspace/workspace.css index 2e87e8b..7117376 100644 --- a/web/js/workspace/workspace.css +++ b/web/js/workspace/workspace.css @@ -212,6 +212,8 @@ main:focus-visible { outline: 2px solid var(--ca-focus); outline-offset: 4px; } /* #249 D20: the viewer details' pair send and history buttons wrap inside the narrow rail at 200% zoom with wider fonts, where the toolkit's `nowrap` would push them past its edge. */ .ca-tools #viewer-details > button { white-space: normal; /* D20 */ } +/* LI-4: "Copy settings summary" after the facts wraps the same way in the narrow rail. */ +.ca-tools #viewer-details .settings-summary { white-space: normal; /* D117 */ } /* The Images page narrows to one column inside a narrow container (the Library-embedded gallery). */ .images-main { container: images-page / inline-size; } @container images-page (inline-size < 600px) { From 08151ca93d219d1b47724ed815827a49bbb57902 Mon Sep 17 00:00:00 2001 From: Vito Date: Fri, 23 Oct 2026 01:58:02 -0700 Subject: [PATCH 2/2] test(library): read one "now" in the fixture and the page across midnight (#287) * test(library): read one "now" in the fixture and the page across midnight The concept fixture recorded each prompt's last use with the database's wall clock at seeding, while the page computed "today" from its own clock at render. A run seeded at 23:59:5x UTC and rendered after midnight read "Used yesterday" against the concept's "Used today" (PR #284, frontend coverage shard 2/3). The concept fixture now takes one instant (optional "now" through the concept reset hook, the wall clock otherwise) for every last use, mtime and run time it writes and returns it as manifest.now; seedConceptAt fixes the browser's Date at that instant. The Library and Images concept specs seed through it, and the two workspace specs that assert "Used today" and the "Today" caption fix the page clock at the time they patch or seed. A new test starts the browser at 23:59:58 UTC, seeds at that instant and passes midnight before either document opens. * test(activity): judge the lost-server backoff by its gaps, not a timed window "lost server clears the pill and marks jobs ended" counted failed job-list re-reads in a 3.5 s waitForTimeout window that started once the test saw the ended job. Re-reads back off 1 s, 2 s, then 4 s, so the third lands 4 s after the second. A runner that noticed the ended job more than 0.5 s late moved the window over the third read (firefox shard 1/2 on #287: 3 reads, expected at most 2). The test now waits for the third failed read and asserts the gaps between reads: at least 2 s, then at least 4 s, with 100 ms allowed for the request being reported late. * test(activity): replace the spec's remaining timer waits with gaps and a run-out clock Three checks in workspace-activity.spec.mjs waited on wall-clock timers: - "lost server": waitForTimeout(2500), then at most 2 list reads. The read after the one that found the restart must be the periodic poll, so the test now waits for it and asserts the gap is at least POLL_MS (less 100 ms for late request reporting). Any extra read lands in that gap. - "200-row cap note" (review M12): waitForTimeout(1500), then no detail read. The page's timers are now Playwright's clock. The test runs one read-throttle interval out, so any read the counter update scheduled is sent before the log opens. Once the log's read has answered, exactly one read must be listed. - "busy start" (review M14): waitForTimeout(7000), then the link toast is still visible. The test now runs the page's clock 7 s on, which fires a 6.5 s clear however slowly the runner got there. RED, each against a temporary product change: POLL_MS 3000 (gap 3004 ms, expected at least 14900), detail re-read on new log lines while the log is closed (an unexpected read), LINK_TOAST_MS 6500 (toast link gone), and BACKOFF_FIRST_MS 200 for the earlier backoff check (gap 407 ms, expected at least 1900). --- tests/browser/concept-inventory.mjs | 11 ++++++ tests/browser/images-concept.spec.mjs | 14 ++++---- tests/browser/library-concept.spec.mjs | 29 +++++++++++++-- tests/browser/server.py | 13 ++++++- tests/browser/workspace-activity.spec.mjs | 42 +++++++++++++++++----- tests/browser/workspace-images.spec.mjs | 4 +++ tests/browser/workspace-library.spec.mjs | 4 ++- tests/browser/workspace_concept_fixture.py | 37 +++++++++++++++++-- tests/test_workspace_concept_fixture.py | 28 +++++++++++++++ 9 files changed, 159 insertions(+), 23 deletions(-) diff --git a/tests/browser/concept-inventory.mjs b/tests/browser/concept-inventory.mjs index 3912286..f7cba70 100644 --- a/tests/browser/concept-inventory.mjs +++ b/tests/browser/concept-inventory.mjs @@ -78,6 +78,17 @@ export async function seedConcept(request,data={}) { return response.json(); } +/** + * Seed the concept fixture and fix the browser's clock at the fixture's own instant (`manifest.now`), so the page and + * the fixture read one "now": a prompt used now reads "Used today" and the caption names the fixture's day even when + * the run crosses midnight between seeding and rendering. Timers keep running; only `Date` stands still. + */ +export async function seedConceptAt(page,request,data={}) { + const manifest=await seedConcept(request,data); + await page.clock.setFixedTime(new Date(manifest.now*1000)); + return manifest; +} + /** * Save `tags` as the current image tag set of the listed file at `path` (root 0) through the real observe and tag * routes (#249 PR C), releasing the capture afterwards; returns the receipt's saved names. diff --git a/tests/browser/images-concept.spec.mjs b/tests/browser/images-concept.spec.mjs index 52e5d0b..08479b3 100644 --- a/tests/browser/images-concept.spec.mjs +++ b/tests/browser/images-concept.spec.mjs @@ -1,7 +1,7 @@ import {writeFile} from 'node:fs/promises'; import {test,expect} from './fixtures.mjs'; import {captureCanonicalState} from './history-canonical-comparison.mjs'; -import {SIZES,THEMES,MOTIONS,seedConcept,openConcept,openProduction,inventoryOf,diffInventory,mutate,stripExact,countCopy,reflow,withoutItems} from './concept-inventory.mjs'; +import {SIZES,THEMES,MOTIONS,seedConceptAt,openConcept,openProduction,inventoryOf,diffInventory,mutate,stripExact,countCopy,reflow,withoutItems} from './concept-inventory.mjs'; // Task C7 of #249: the production Images page against the immutable concept, on the concept-shaped real fixture (24 // images of the concept's six prompts, its seeds, sizes and favorites). Heading, toolbar, filter row, caption, grid, @@ -85,7 +85,7 @@ function listInfo(card,actionsWidth) { /** Recorded Images deviations only (spec §8); everything else in the concept inventory must equal production. */ const nocase=(a,b)=>{const x=a.toLowerCase(),y=b.toLowerCase();return xy?1:ab?1:0;}; -export function mapImagesConcept(reference,{manifest,now=new Date()}) { +export function mapImagesConcept(reference,{manifest,now=new Date(manifest.now*1000)}) { const paths=new Map(manifest.images.map(image=>[image.filename,image.path])); // D14: the sort appends production's two sorts. Save view is the concept's own (saved views, #249 D16 retired). const toolbar={...reference.toolbar}; @@ -318,7 +318,7 @@ async function behaviorsOf(page,scope) { return {hover,opened,viewerTitle,focusAfterViewer,selected,layouts,search,single}; } -test.beforeEach(async({request},testInfo)=>{testInfo.manifest=await seedConcept(request);}); +test.beforeEach(async({page,request},testInfo)=>{testInfo.manifest=await seedConceptAt(page,request);}); for(const [width,height] of SIZES)for(const theme of THEMES)test(`images page geometry, tokens, controls and behaviors match the concept ${width}x${height} ${theme}`,async({page,request},testInfo)=>{ test.setTimeout(240_000); @@ -348,7 +348,7 @@ for(const [width,height] of SIZES)for(const theme of THEMES)test(`images page ge importDiff:diffInventory(mapImportConcept(referenceImport),actualImport),referenceBehaviors,actualBehaviors}; } // Load more in production: a fixture past one listing page appends one batch and shows the concept's toast. - testInfo.manifest=await seedConcept(request,{extra_images:LOAD_MORE_EXTRA}); + testInfo.manifest=await seedConceptAt(page,request,{extra_images:LOAD_MORE_EXTRA}); for(const motion of MOTIONS) { const total=FIXTURE_IMAGES+LOAD_MORE_EXTRA; await openProductionLoaded(page,theme,motion,total); @@ -514,7 +514,7 @@ test('one appended image reads in the singular',async({page,request})=>{ test.setTimeout(120_000); await page.setViewportSize({width:1600,height:1100}); const total=PRODUCTION_BATCH+1; - await seedConcept(request,{extra_images:total-FIXTURE_IMAGES}); + await seedConceptAt(page,request,{extra_images:total-FIXTURE_IMAGES}); await openProductionLoaded(page,'dark','no-preference',total); await expect(page.locator('.infinite-continuation > p').first()).toHaveText(countCopy(`${PRODUCTION_BATCH} of ${total} images · more load as you scroll`)); // A dispatched press: scrolling the button into view lets the page's own observer load the one image first. @@ -530,7 +530,7 @@ test('one image appended by scrolling reads in the singular',async({page,request test.setTimeout(120_000); await page.setViewportSize({width:1600,height:1100}); const total=PRODUCTION_BATCH+1; - await seedConcept(request,{extra_images:total-FIXTURE_IMAGES}); + await seedConceptAt(page,request,{extra_images:total-FIXTURE_IMAGES}); await openProductionLoaded(page,'dark','no-preference',total); await expect(page.locator('#result-count')).toHaveText(new RegExp(`^${PRODUCTION_BATCH} of ${total} images`)); await page.locator('.infinite-continuation').scrollIntoViewIfNeeded(); @@ -551,7 +551,7 @@ test('one footer height for the collection (D3)',async({page,request})=>{ const reference=await inventoryOf(page,'#main'); expect(reference.grid.columns).toBe(2); expect(reference.cards.every(card=>card.info.p.height>parseFloat(card.info.p.lineHeight))).toBe(true); - const manifest=await seedConcept(request,{seedless_images:2,short_seedless:true}); + const manifest=await seedConceptAt(page,request,{seedless_images:2,short_seedless:true}); await openProductionLoaded(page,'dark','no-preference',FIXTURE_IMAGES+2); const actual=await inventoryOf(page,'#workspace-main'); const box=card=>({left:card.left,top:card.top,width:card.width,height:card.height}); diff --git a/tests/browser/library-concept.spec.mjs b/tests/browser/library-concept.spec.mjs index eeab9b9..8e85bae 100644 --- a/tests/browser/library-concept.spec.mjs +++ b/tests/browser/library-concept.spec.mjs @@ -1,7 +1,7 @@ import {writeFile} from 'node:fs/promises'; import {test,expect} from './fixtures.mjs'; import {captureCanonicalState} from './history-canonical-comparison.mjs'; -import {SIZES,THEMES,MOTIONS,seedConcept,openConcept,openProduction,inventoryOf,diffInventory,mutate,stripExact,countCopy,reflow} from './concept-inventory.mjs'; +import {SIZES,THEMES,MOTIONS,seedConceptAt,openConcept,openProduction,inventoryOf,diffInventory,mutate,stripExact,countCopy,reflow} from './concept-inventory.mjs'; // Task E3 of #249: the production Prompt library shelf against the immutable concept (app.js renderLibrary a572–586, // style.css s648–708), on the concept-shaped real fixture (the concept's six prompts with their negatives, categories, @@ -37,7 +37,8 @@ export function mapLibraryConcept(reference) { // D43: tag chips come in the store's alphabetical order; the row flows again from the concept's own chips. tags:sortedTags(card.tags), // D23: the stars are aria-hidden, with a visually hidden "Rated N out of 5" spoken in their place. The fixture's - // run_count (4) and last_used_at (now) give the concept's own "4 runs" and "Used today". The two-line clamp is + // run_count (4) and last_used_at (its own "now", where the page's clock stands) give the concept's own "4 runs" + // and "Used today". The two-line clamp is // applied below through `clampedCards`, measured on the concept with `CLAMP_CSS` (its samples wrap at 390px). footer:{...card.footer,facts:{...card.footer.facts,spoken:card.footer.facts.spoken.replace(/^(★+)/,stars=>`Rated ${stars.length} out of 5`)}}})); return {...reference,library:{...library,toolbar, @@ -238,7 +239,8 @@ async function openHost(context) { } test.beforeEach(async({page,request},testInfo)=>{ - testInfo.manifest=await seedConcept(request); + // The page's clock stands at the fixture's own "now", so its last use reads "Used today" on either side of midnight. + testInfo.manifest=await seedConceptAt(page,request); // Both documents copy through the clipboard; the stub records what they wrote. await page.addInitScript(()=>{window.copied=[];Object.defineProperty(navigator,'clipboard',{configurable:true,value:{writeText:async text=>{window.copied.push(text);}}});}); }); @@ -322,6 +324,27 @@ for(const theme of THEMES)test(`library grid and cards match the concept 1800x11 expect(compare(reference,actual,{sections:['library'],library:['grid','cards','trailing']})).toEqual([]); }); +// PR #284's CI run: the fixture recorded the last use at 23:59:5x UTC and the shelf rendered at 00:00:05, so production +// read "Used yesterday" against the concept's "Used today". Here the browser's wall clock starts at 23:59:58 UTC, the +// fixture records its use at that instant, and midnight passes before either document opens. +const BEFORE_MIDNIGHT=Date.UTC(2026,9,22,23,59,58); +const PAST_MIDNIGHT_MS=5_000; +test('a run that crosses midnight still reads the concept fixture\'s day',async({page,request})=>{ + await page.setViewportSize({width:1800,height:1100}); + await page.clock.install({time:BEFORE_MIDNIGHT}); + const manifest=await seedConceptAt(page,request,{now:BEFORE_MIDNIGHT/1000}); + expect(manifest.now*1000,'the fixture\'s now').toBe(BEFORE_MIDNIGHT); + const used=(await (await request.get('/prompt_manager/library')).json()).items.map(item=>Date.parse(item.last_used_at)); + expect(used,'every last use at the fixture\'s now').toEqual(Array(CONCEPT_PROMPTS).fill(BEFORE_MIDNIGHT)); + await page.clock.fastForward(PAST_MIDNIGHT_MS); + await openConceptLibrary(page,'dark','no-preference'); + const reference=await conceptInventory(page); + await openProductionLibrary(page,'dark','no-preference'); + const actual=await inventoryOf(page,'#workspace-main'); + expect(actual.library.cards.map(card=>card.footer.facts.text.replace(/^★+ · /,''))).toEqual(Array(CONCEPT_PROMPTS).fill('Used today')); + expect(compare(reference,actual,{sections:['library'],library:['grid','cards','trailing']})).toEqual([]); +}); + // The comparison is only worth something if it notices a change (spec §7 mutation check): one CSS mutation (the footer // padding) and one DOM mutation (the negative-variants chip removed), each applied after an exact match. test('library comparison detects mutations',async({page})=>{ diff --git a/tests/browser/server.py b/tests/browser/server.py index 9764aa7..212109e 100644 --- a/tests/browser/server.py +++ b/tests/browser/server.py @@ -23,6 +23,7 @@ from tests.browser.workspace_activity_fixture import register_activity_commands from tests.browser.workspace_concept_fixture import ( MAX_EXTRA_IMAGES as CONCEPT_MAX_EXTRA_IMAGES, MAX_SEEDLESS_IMAGES as CONCEPT_MAX_SEEDLESS_IMAGES, + MAX_EPOCH_SECONDS as CONCEPT_MAX_EPOCH_SECONDS, seed_workspace_concept, ) from tests.browser.workspace_visual_fixture import seed_workspace_visual @@ -489,8 +490,17 @@ def create_app(root: Path) -> web.Application: if ( request.query or not isinstance(data, dict) - or set(data) - set(limits) - {"short_seedless"} + or set(data) - set(limits) - {"short_seedless", "now"} or not isinstance(data.get("short_seedless", False), bool) + # A chosen "now" (epoch seconds) pins every time the fixture writes. + or ( + "now" in data + and ( + isinstance(data["now"], bool) + or not isinstance(data["now"], (int, float)) + or not 0 < data["now"] < CONCEPT_MAX_EPOCH_SECONDS + ) + ) or any( isinstance(data.get(key, 0), bool) or not isinstance(data.get(key, 0), int) @@ -510,6 +520,7 @@ def create_app(root: Path) -> web.Application: extra_images=data.get("extra_images", 0), seedless_images=data.get("seedless_images", 0), short_seedless=data.get("short_seedless", False), + now=data.get("now"), ) ) return web.json_response({"success": True, **manifest}) diff --git a/tests/browser/workspace-activity.spec.mjs b/tests/browser/workspace-activity.spec.mjs index 4479751..cbd848c 100644 --- a/tests/browser/workspace-activity.spec.mjs +++ b/tests/browser/workspace-activity.spec.mjs @@ -2,6 +2,13 @@ import { startCoverage, saveCoverage } from '../../tools/vendor/browser-coverage import { test, expect } from './fixtures.mjs'; import { seedConcept, openConcept, openProduction } from './concept-inventory.mjs'; +// The Activity store's periodic list read (activity-store.mjs POLL_MS) and the detail view's read throttle +// (activity-job-view.mjs DETAIL_INTERVAL_MS). +const POLL_MS = 15_000; +const DETAIL_INTERVAL_MS = 1_000; +// A request is reported to the test a little after the browser sends it; that delay is not a shorter wait. +const REPORT_SLACK_MS = 100; + // Activity (#249 Activity-1): the concept's Activity page (app.js renderActivity 732–738), its top-bar button // (index.html 51–52) and sidebar row (app.js ~341), with the recorded D52 (counts of running jobs), D53 (the progress // pill) and D54 (real job items). Fake jobs come from tests/browser/workspace_activity_fixture.py. @@ -278,6 +285,8 @@ test('reload during a scan reattaches to the running job', async ({ page, reques }); test('lost server clears the pill and marks jobs ended', async ({ page, request }) => { + // A poll interval after the restart, then failed re-reads backing off for 1 + 2 + 4 s. + test.setTimeout(90_000); await page.setViewportSize({ width: 1600, height: 1100 }); const job = await startJob(request); await step(request, job.id, { processed: 4000 }); @@ -294,9 +303,12 @@ test('lost server clears the pill and marks jobs ended', async ({ page, request await expect(items(page).first().locator('p')).toHaveText(LOST); await expect(items(page).first().locator('progress, .row-actions')).toHaveCount(0); await expect(navRow(page).locator('.nav-count')).toHaveCount(0); - // One re-read found the restart; there is no retry storm and no finish toast for a job that only vanished. - await page.waitForTimeout(2500); - expect(reads.length).toBeLessThanOrEqual(2); + // One re-read found the restart; there is no retry storm and no finish toast for a job that only vanished. The + // read after it is the periodic one, a whole poll interval later: any extra read lands in that gap and fails it. + const found = reads.length; + expect(found, 'reads that found the restart').toBeGreaterThanOrEqual(1); + await expect.poll(() => reads.length, { timeout: POLL_MS + 10_000 }).toBeGreaterThan(found); + expect(reads[found] - reads[found - 1], 'the next read waits for the poll').toBeGreaterThanOrEqual(POLL_MS - REPORT_SLACK_MS); await expect(toast(page)).toHaveText(''); // A server that cannot be read at all also ends the running job, then is read again with a growing backoff. @@ -308,9 +320,12 @@ test('lost server clears the pill and marks jobs ended', async ({ page, request await expect(await request.post('/__test__/jobs/restart')).toBeOK(); await expect(pill(page)).toBeHidden(); await expect(items(page).filter({ hasText: LOST })).toHaveCount(1); - await page.waitForTimeout(3500); - // 1 s, then 2 s: at most two re-reads in 3.5 s. - expect(failed.length).toBeLessThanOrEqual(2); + // 1 s, then 2 s, then 4 s: each failed re-read waits twice as long as the one before. The gaps between the + // reads themselves are the evidence, so a slow runner noticing the ended job late cannot add a read to a window. + await expect.poll(() => failed.length, { timeout: 20_000 }).toBeGreaterThanOrEqual(3); + const gaps = failed.slice(1, 3).map((at, index) => at - failed[index]); + expect(gaps[0]).toBeGreaterThanOrEqual(2000 - REPORT_SLACK_MS); + expect(gaps[1]).toBeGreaterThanOrEqual(4000 - REPORT_SLACK_MS); await page.unroute('**/prompt_manager/jobs**'); expect(second.id).not.toBe(job.id); }); @@ -607,6 +622,8 @@ test('filter narrows the selected outcome', async ({ page, request }) => { test('job view renders 200-row cap note', async ({ page, request }) => { await page.setViewportSize({ width: 1600, height: 1100 }); + // The page's timers are Playwright's, running at real speed, so the M12 check below can run a read throttle out. + await page.clock.install(); const job = await startJob(request); await step(request, job.id, { processed: 260, bulk: { group: 'added', count: 250 }, records: [ ...Array.from({ length: 10 }, (_, index) => ({ group: 'no_metadata', path: `misc/plain_${index}.png`, detail: 'No prompt metadata in the file' })), @@ -646,11 +663,15 @@ test('job view renders 200-row cap note', async ({ page, request }) => { page.on('request', item => { if (new URL(item.url()).pathname === `/prompt_manager/jobs/${job.id}`) reads.push(Date.now()); }); await step(request, job.id, { processed: 300, bulk: { group: 'added', count: 40 } }); await expect(tiles(page).first().locator('dd')).toHaveText('290'); - await page.waitForTimeout(1500); + // Every read the counter update could have scheduled is due within one throttle interval: run it out, so any such + // read is sent before the log opens. Requests reach the test in the order they were sent, so once the log's read + // has answered, a read sent before it would already be listed. + await page.clock.runFor(DETAIL_INTERVAL_MS); expect(reads).toEqual([]); await scanLog(page).locator('summary').click(); await expect.poll(() => reads.length).toBe(1); await expect(scanLog(page).locator('pre')).toContainText('bulk/file_00039.png'); + expect(reads, 'only the log\'s own read').toHaveLength(1); }); test('cancel scan ends cancelled with partial counts', async ({ page, request }) => { @@ -705,14 +726,17 @@ test('a held legacy job shows no Cancel in the list or its view', async ({ page, test('busy start names the running job', async ({ page, request }) => { await page.setViewportSize({ width: 1600, height: 1100 }); + // The page's timers are Playwright's, so the toast's lifetime below is run out rather than waited for. + await page.clock.install(); const running = await startJob(request, { title: 'Database maintenance', kind: 'maintenance' }); await startFromImport(page); await expect(toast(page)).toHaveText('Another job is running: Database maintenance.'); await expect(toast(page).getByRole('link', { name: 'Database maintenance', exact: true })).toHaveAttribute('href', `#/activity/${running.id}`); await expect(page).toHaveURL(/#\/images$/); expect((await listed(request)).map(item => item.id)).toEqual([running.id]); - // Review M14: a toast with a link outlasts the plain 6.5 s, so the link stays reachable. - await page.waitForTimeout(7000); + // Review M14: a toast with a link outlasts the plain 6.5 s, so the link stays reachable. Running the page's timers + // 7 s on fires a 6.5 s clear for certain, however slowly this runner reached this line. + await page.clock.runFor(7000); await expect(toast(page).getByRole('link', { name: 'Database maintenance', exact: true })).toBeVisible(); await toast(page).getByRole('link', { name: 'Database maintenance', exact: true }).click(); await expect(heading(page).locator('h1')).toHaveText('Database maintenance'); diff --git a/tests/browser/workspace-images.spec.mjs b/tests/browser/workspace-images.spec.mjs index 483227c..4f544cf 100644 --- a/tests/browser/workspace-images.spec.mjs +++ b/tests/browser/workspace-images.spec.mjs @@ -907,6 +907,10 @@ test('browser Back closes the open Images dialog and leaves the next page usable test('count line shows images and positive prompts', async ({ page, request }) => { await page.addInitScript(() => { window.IntersectionObserver = undefined; }); + // D17's "Today" is the newest file's day: the page's clock stands at that file's mtime, so the fixture's day and + // the page's agree on either side of midnight. + const { images } = await (await request.get('/prompt_manager/images/output?mode=workspace&limit=40')).json(); + await page.clock.setFixedTime(new Date(Math.max(...images.map(image => image.modified_time)) * 1000)); await page.goto(workspace); await expect(cards(page)).toHaveCount(2); await expect(caption(page).locator('#result-count')).toHaveText('2 of 2 images · 2 positive prompts'); diff --git a/tests/browser/workspace-library.spec.mjs b/tests/browser/workspace-library.spec.mjs index 7055766..5ef235f 100644 --- a/tests/browser/workspace-library.spec.mjs +++ b/tests/browser/workspace-library.spec.mjs @@ -610,7 +610,9 @@ test('card matches the concept and never wraps the category mid-word',async({pag await expect(await request.post('/prompt_manager/bulk/category',{data:{prompt_ids:[dual.id],category:''}})).toBeOK(); // A long saved title fills the title row, so only the chip's own min-content keeps "Uncategorized" and "asian" whole. const wide='A remarkably long saved positive prompt title that fills the whole card title row'; - await patchShelf(page,item=>item.id===cat.id?{run_count:4,last_used_at:new Date().toISOString(),rating:5}:item.id===dual.id||item.id===dog.id?{title:wide,run_count:1,last_used_at:null,rating:null}:{}); + // One "now" for the patched last use and the page's clock, so it reads "Used today" on either side of midnight. + const usedAt=new Date();await page.clock.setFixedTime(usedAt); + await patchShelf(page,item=>item.id===cat.id?{run_count:4,last_used_at:usedAt.toISOString(),rating:5}:item.id===dual.id||item.id===dog.id?{title:wide,run_count:1,last_used_at:null,rating:null}:{}); for(const [width,height] of [[1600,1100],[390,844]]) { await page.setViewportSize({width,height});await page.goto(route);await expect(cards(page)).toHaveCount(3); const card=page.locator(`article[data-prompt-id="${cat.id}"]`); diff --git a/tests/browser/workspace_concept_fixture.py b/tests/browser/workspace_concept_fixture.py index b22c362..bcb306f 100644 --- a/tests/browser/workspace_concept_fixture.py +++ b/tests/browser/workspace_concept_fixture.py @@ -11,6 +11,7 @@ the same sidebar counts (24 images, 6 prompts, 15 tags). Nothing is mocked. from __future__ import annotations from dataclasses import dataclass +import datetime import json import math import os @@ -157,6 +158,8 @@ CONCEPT_MODEL = "illustrative-model.safetensors" MAX_EXTRA_IMAGES = 120 # Unlinked, seedless images (D11 "W × H · PNG") newer than the concept's, for D3 checks. MAX_SEEDLESS_IMAGES = 2 +# A test's chosen "now" (epoch seconds) stays before the year 3000. +MAX_EPOCH_SECONDS = 32_503_680_000 SEEDLESS_SIZE = (1536, 1152) # The same 4:3 shape with a short "96 × 72 · PNG" subtitle that stays on one line at # 390px beside the card's Info and Tag (the D3 footer check). @@ -342,6 +345,17 @@ def _bounded(name: str, value: int, maximum: int) -> None: raise ValueError(f"{name} is out of range") +def _instant(now: float | None) -> float: + """The fixture's one "now": ``now`` itself, or the wall clock when omitted.""" + if now is None: + return time.time() + if isinstance(now, bool) or not isinstance(now, (int, float)): + raise TypeError("now must be a number of epoch seconds") + if not 0 < now < MAX_EPOCH_SECONDS: + raise ValueError("now is out of range") + return float(now) + + def seed_workspace_concept( api: PromptManagerAPI, root: Path, @@ -349,9 +363,16 @@ def seed_workspace_concept( extra_images: int = 0, seedless_images: int = 0, short_seedless: bool = False, + now: float | None = None, ) -> dict: """Replace this server's disposable rows and files with the concept's data. + Every relative time the fixture writes (the prompts' last use, the files' + mtimes, the runs' observation times) is taken from one instant, ``now`` + (epoch seconds, the wall clock when omitted), returned as ``manifest["now"]``. + A browser whose clock is fixed at that instant reads the concept's "Used + today" and caption day however close to midnight the run starts. + ``extra_images`` continues the concept's rounds (same prompts, dimensions and seed rule) after its 24 images, for bounded-rendering and Load more checks. ``seedless_images`` adds unlinked PNGs without metadata, newest of all; @@ -361,6 +382,10 @@ def seed_workspace_concept( raise TypeError("short_seedless must be a boolean") _bounded("extra_images", extra_images, MAX_EXTRA_IMAGES) _bounded("seedless_images", seedless_images, MAX_SEEDLESS_IMAGES) + now = _instant(now) + used_at = datetime.datetime.fromtimestamp(now, datetime.timezone.utc).isoformat( + timespec="microseconds" + ) _clear(api, root) db = api.db epoch = db.get_execution_epoch() @@ -385,8 +410,15 @@ def seed_workspace_concept( db.update_prompt_pair_metadata(pair_ids[0], title=first_name) for name, text in prompt.negatives[1:]: pair_ids.append(db.save_prompt_pair(prompt.positive, text, title=name)) - # Real queue-hook counting (D23): four runs, the last one now. + # Real queue-hook counting (D23): four runs, the last one now, at the + # fixture's own instant rather than the database's later wall clock. db.record_prompt_use(positive_id, times=CONCEPT_RUN_COUNT) + with db.model.get_connection() as conn: + conn.execute( + "UPDATE prompts SET last_used_at = ? WHERE id = ?", + (used_at, positive_id), + ) + conn.commit() prompts.insert( 0, {"id": prompt.id, "positive_id": positive_id, "pair_ids": pair_ids} ) @@ -400,7 +432,6 @@ def seed_workspace_concept( favorite_root = _favorite_root_key(list(api._get_all_output_dirs())[0]) total = len(CONCEPT_PROMPTS) * CONCEPT_IMAGE_ROUNDS + extra_images rounds = math.ceil(total / len(CONCEPT_PROMPTS)) - now = time.time() images, runs = [], [] slots = [ (round_index, prompt_index, prompt) @@ -484,6 +515,8 @@ def seed_workspace_concept( api.invalidate_gallery_cache() return { "epoch": epoch, + # The fixture's "now" (epoch seconds), for the browser's fixed clock. + "now": now, # The newest file's mtime (epoch seconds), for the D17 caption date. "newest_modified": now - 10 if seedless_images else now - 60, "seedless": seedless, diff --git a/tests/test_workspace_concept_fixture.py b/tests/test_workspace_concept_fixture.py index f301de6..f855211 100644 --- a/tests/test_workspace_concept_fixture.py +++ b/tests/test_workspace_concept_fixture.py @@ -1,7 +1,9 @@ """The concept fixture files carry the concept inspector facts (app.js:400-414).""" import json +import math import tempfile +import time import unittest from pathlib import Path @@ -15,6 +17,8 @@ except ImportError: # discovered with tests/ as the top-level directory from tests.browser.workspace_concept_fixture import ( CONCEPT_MODEL, CONCEPT_PROMPTS, + MAX_EPOCH_SECONDS, + _instant, write_concept_png, ) from utils.prompt_inspector import inspect_prompt_evidence, read_inspection_file @@ -80,5 +84,29 @@ class TestWorkspaceConceptFixture(unittest.TestCase): self.assertEqual((image["width"], image["height"]), size) +class TestConceptFixtureInstant(unittest.TestCase): + """One "now" for every relative time the fixture writes (PR #284's midnight).""" + + def test_a_chosen_instant_is_kept(self): + self.assertEqual(_instant(1_792_713_598), 1_792_713_598.0) + self.assertEqual(_instant(1_792_713_598.25), 1_792_713_598.25) + + def test_the_wall_clock_when_omitted(self): + before = time.time() + now = _instant(None) + self.assertLessEqual(before, now) + self.assertLessEqual(now, time.time()) + + def test_a_non_number_is_refused(self): + for value in (True, "1792713598", [1]): + with self.subTest(value=value), self.assertRaises(TypeError): + _instant(value) + + def test_an_instant_out_of_range_is_refused(self): + for value in (0, -1, MAX_EPOCH_SECONDS, math.inf, math.nan): + with self.subTest(value=value), self.assertRaises(ValueError): + _instant(value) + + if __name__ == "__main__": unittest.main()