From b14b87f98f5f45b2bcffac100f6a9e8f66b83357 Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Thu, 22 Oct 2026 17:18:14 -0700 Subject: [PATCH] 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. --- .../local-inspect/resolver-vectors.json | 1 + tests/js/support/local-inspect-oracle.mjs | 22 + tests/js/workspace-local-resolver.test.js | 110 ++ tests/local_resolver_cases.py | 1307 +++++++++++++++++ tests/test_local_inspect_parity.py | 168 +++ tools/vendor/frontend-coverage-baseline.json | 20 +- web/js/workspace/local-resolver-support.mjs | 260 ++++ web/js/workspace/local-resolver.mjs | 776 ++++++++++ web/js/workspace/py-json.mjs | 239 +++ 9 files changed, 2902 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/local-inspect/resolver-vectors.json create mode 100644 tests/js/workspace-local-resolver.test.js create mode 100644 tests/local_resolver_cases.py 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/py-json.mjs diff --git a/tests/fixtures/local-inspect/resolver-vectors.json b/tests/fixtures/local-inspect/resolver-vectors.json new file mode 100644 index 00000000..dcece2f6 --- /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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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": null, "gap": true, "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": null, "gap": true, "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": null, "gap": true, "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"}}, "gap": false, "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": {"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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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"}}, "gap": false, "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]}}}"}}], "version": 1} diff --git a/tests/js/support/local-inspect-oracle.mjs b/tests/js/support/local-inspect-oracle.mjs index 61711ced..3a02a7ff 100644 --- a/tests/js/support/local-inspect-oracle.mjs +++ b/tests/js/support/local-inspect-oracle.mjs @@ -14,6 +14,9 @@ // 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} or {gap: true}: resolveLocalEvidence of its +// {path}'s local read, or of its {records} texts, with the repository semantics table +// (gap: a path the port leaves to Task 9). import fs from 'node:fs'; import path from 'node:path'; import { createRequire } from 'node:module'; @@ -28,6 +31,18 @@ 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, LocalResolverGap } = await import(moduleUrl(path.join(web, 'local-resolver.mjs'))); +const semantics = compileSemantics(JSON.parse(fs.readFileSync(path.join(here, '..', '..', '..', 'web', 'js', 'inspection-semantics.json'), 'utf8'))); + +/** The local evidence for one set of record texts, or {gap: true}. */ +function resolved(records) { + try { + return { evidence: resolveLocalEvidence(records, semantics) }; + } catch (error) { + if (error instanceof LocalResolverGap) return { gap: true }; + throw error; + } +} const selectionRead = (selection) => selection.status === 'complete' ? { records: selection.records, record_formats: selection.record_formats, carrierText: selection.carrierText, limited: selection.limited } : null; @@ -37,6 +52,13 @@ 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 { classification, result } = await readLocalFile(await fs.openAsBlob(entry.path), { pngMetadata }); + const read = classification === null ? null : toInspectionRead(classification, result).read; + output[name] = read === null ? { unreadable: true } : resolved(read.records); + continue; + } if (entry.records !== undefined) { const read = entry.records === null ? null : { records: entry.records, diff --git a/tests/js/workspace-local-resolver.test.js b/tests/js/workspace-local-resolver.test.js new file mode 100644 index 00000000..af43fd0e --- /dev/null +++ b/tests/js/workspace-local-resolver.test.js @@ -0,0 +1,110 @@ +// PR L3 Task 8: 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))); +}); + +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('several samplers and A1111 parameters are left to Task 9', () => { + assert.throws(() => resolver.resolveLocalEvidence({prompt: JSON.stringify(base({'9': sampler()}))}, semantics), resolver.LocalResolverGap); + assert.throws(() => resolver.resolveLocalEvidence({parameters: 'a fox\nSteps: 20, Sampler: euler'}, semantics), resolver.LocalResolverGap); +}); + +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, gap, evidence} of vectors) { + if (gap) { + assert.throws(() => resolver.resolveLocalEvidence(records, semantics), resolver.LocalResolverGap, name); + continue; + } + assert.deepEqual(canonical(resolver.resolveLocalEvidence(records, semantics)), canonical(evidence), name); + compared++; + } + assert.ok(compared > 140, `compared ${compared}`); +}); diff --git a/tests/local_resolver_cases.py b/tests/local_resolver_cases.py new file mode 100644 index 00000000..f3cb8a57 --- /dev/null +++ b/tests/local_resolver_cases.py @@ -0,0 +1,1307 @@ +"""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). +""" + +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", + ) + 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 + + +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 committed_vectors(): + """The committed record sets with the server's evidence, in a stable order.""" + cases = { + name: records + for name, records in golden_cases().items() + if len(json.dumps(records)) <= MAX_VECTOR_CHARS + } + cases.update(fuzz_cases(*COMMITTED_FUZZ)) + vectors = [] + for name, records in cases.items(): + gap = not single_chain(records) + evidence = ( + None + if gap + else inspect_prompt_evidence(records, None, profile=INSPECTION_PROFILE) + ) + vectors.append( + {"name": name, "records": records, "gap": gap, "evidence": evidence} + ) + return {"version": 1, "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/test_local_inspect_parity.py b/tests/test_local_inspect_parity.py index 9fdfdd98..f9a0950e 100644 --- a/tests/test_local_inspect_parity.py +++ b/tests/test_local_inspect_parity.py @@ -51,12 +51,17 @@ from utils.prompt_inspector import ( read_inspection_file, ) +from utils.prompt_inspector import inspect_prompt_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.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 from open_handles import assert_closed from test_utils_video_metadata import HAVE_FFMPEG, write_video @@ -1111,5 +1116,168 @@ 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`` (PR L3 Task 8). + + Python is the oracle: every expected value is the server's own answer on the + same record texts. Task 8 ports one sampler's tracing; a record set whose + graph has several sampler candidates or a detailer stage, or only A1111 + ``parameters``, is a gap the port reports until Task 9, and exactly those + are gaps (``local_resolver_cases.single_chain`` decides from the server's + table). + """ + + 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 equal or a recorded gap; 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] + self.assertEqual( + local.get("gap", False), + not resolver_cases.single_chain(records), + "a gap is exactly a Task 9 path", + ) + if local.get("gap"): + continue + 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 = gaps = 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.assertEqual(local, {"unreadable": True}) + continue + self.assertEqual( + local.get("gap", False), not resolver_cases.single_chain(records) + ) + if local.get("gap"): + gaps += 1 + 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 + # f01, f09 (several samplers) and f19 (multistage detailer) wait for Task 9. + self.assertGreaterEqual(compared, 20) + self.assertGreaterEqual(gaps, 1) + + 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_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 6869e83a..db441041 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 }, @@ -335,6 +335,18 @@ "functions": 98, "statements": 97 }, + "workspace/local-resolver-support.mjs": { + "lines": 96, + "branches": 80, + "functions": 98, + "statements": 96 + }, + "workspace/local-resolver.mjs": { + "lines": 95, + "branches": 83, + "functions": 98, + "statements": 95 + }, "workspace/local-session.mjs": { "lines": 98, "branches": 92, @@ -377,6 +389,12 @@ "functions": 98, "statements": 98 }, + "workspace/py-json.mjs": { + "lines": 97, + "branches": 91, + "functions": 98, + "statements": 97 + }, "workspace/recorded-run.mjs": { "lines": 95, "branches": 83, diff --git a/web/js/workspace/local-resolver-support.mjs b/web/js/workspace/local-resolver-support.mjs new file mode 100644 index 00000000..b9328b31 --- /dev/null +++ b/web/js/workspace/local-resolver-support.mjs @@ -0,0 +1,260 @@ +// Tables, evidence reader, bounds and outcome lines for local-resolver.mjs (#249 local Inspect, PR L3 Task 8): +// 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'; + +/** A resolution path Task 9 ports (several samplers, a detailer stage, A1111 parameters). */ +export class LocalResolverGap extends Error { + constructor(message) { + super(message); + this.name = 'LocalResolverGap'; + } +} + +/** 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). +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 MULTISTAGE_UNATTRIBUTED_REASON = 'Multistage sampler ancestry is ambiguous'; +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.", + 'Media metadata could not be read': '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 00000000..bde4db2f --- /dev/null +++ b/web/js/workspace/local-resolver.mjs @@ -0,0 +1,776 @@ +// 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 ports execution evidence and graph tracing for one sampler. Candidate selection among several samplers, +// detailer stages and A1111 `parameters` are Task 9; until then they raise `LocalResolverGap`. 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, + DETAILER, + Diverging, + EMPTY_POSITIVE, + EMPTY_POSITIVE_REASON, + GUIDER_ABSENT_REASON, + INCOMPATIBLE_SLOT, + LocalResolverGap, + 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, + UNVERIFIABLE_CODES, + Unresolved, + ZEROED_SOURCE, + compileSemantics, + explained, + isLink, + nodeRef, + readPairExecution, + result, + sideOf, + slotKey, +} from './local-resolver-support.mjs'; + +export { LocalResolverGap, 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); + } + + /** One sampler's result. A detailer stage compared with its upstream stages is Task 9. */ + stage(samplerId, later) { + if (later.size >= this.maxDepth) return result('unresolved', { samplerId, reason: 'Resolution depth limit reached', reasonCode: 'depth-limit' }); + const own = this.sides(samplerId); + if (own.state === 'unresolved') return own; + const [name] = this.node(samplerId); + const entry = this.semantics.samplers.get(name); + if (entry === undefined || entry.strategy !== DETAILER) return own; + throw new LocalResolverGap('Detailer stages are compared in Task 9'); + } + + branches(samplerId) { + const pending = [new Map()], results = []; + try { + while (pending.length) { + this.choices = pending.shift(); + try { + results.push(this.stage(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); + } + } +} + +const roleText = side => side !== null && typeof side === 'object' ? side.text : null; +const outcomeKey = item => JSON.stringify([item.state, roleText(item.positive), roleText(item.negative)]); + +/** `_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' }); +} + +/** Python `kind in mapping` for a workflow `type`: an unhashable list or dict raises `TypeError` there. */ +function hashable(value) { + if (isList(value) || isDict(value)) throw new TypeError("unhashable type in workflow node 'type'"); + return value; +} + +/** `_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)}`; + if (typeof hashable(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')) throw new LocalResolverGap('A1111 parameters are resolved in Task 9'); + 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 }); + const overwritten = metadata.has('prompt') ? overwrittenPromptNodes(pyGet(metadata, 'workflow'), graph) : new Set(); + const resolver = new GraphResolver(graph, metadata.has('prompt') ? metadata : null, semantics, overwritten); + const samplerIds = [...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 || samplerIds.some(id => semantics.samplers.get(graph.get(id).get('class_type')).strategy === DETAILER)) { + throw new LocalResolverGap('Several sampler candidates are selected in Task 9'); + } + 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; +} + +/** + * `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: 'Prompt evidence is malformed', 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/py-json.mjs b/web/js/workspace/py-json.mjs new file mode 100644 index 00000000..54d7dd92 --- /dev/null +++ b/web/js/workspace/py-json.mjs @@ -0,0 +1,239 @@ +// 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; +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 = []; + let result; + for (;;) { + let value; + if (text[pos] === '{') { + pos++; skip(); + 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] === '[') { + pos++; skip(); + 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()`). +const SPACE = '\\t\\n\\x0b\\x0c\\r\\x1c-\\x1f \\x85\\xa0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000'; +const LEADING = new RegExp(`^[${SPACE}]+`), TRAILING = new RegExp(`[${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;