PreFlight: Report (IG/TikTok/X)
Report — the verdict node that says 'probably fine, at worst demoted'
- image
- report_json
- summary
- record_id
- image
What it's for
PreFlight: Report predicts how Instagram, TikTok and X would treat a piece of content, per platform - and unlike most things in ComfyUI wearing the word "report", it calls nothing. No API, no key, no model: it's a deterministic rules engine over the observation JSON from PreFlight: Observe, so it runs instantly and answers the same twice.
That separation is the point of the pack: the sensor describes the image, this node applies the rules, and when a verdict looks wrong you can tell which half failed. And because observations are stored separately from verdicts, you can re-judge old content against updated rules without re-running Qwen-VL. Keep the framing straight, though - this predicts platform treatment, not legality, and most of what decides enforcement is invisible to it: account history, bio, link patterns, region, cadence.
How it works
It parses the observations_json string, checks the observation's meta.schema_version against the versions the engine understands, then applies its rules. An unrecognised schema - or an {"error": ...} object from Observe - fails closed to UNKNOWN rather than silently judging a record it can't read.
The caption you type and any text the model read inside the image are scanned together, as one blob. That's a genuinely good design decision: a fanvue.com watermark burned into a frame flags exactly like a caption link would, because to a platform's text classifier they are the same signal. Video is inferred rather than declared - more than one analysed frame and the motion rules apply - and every report carries the engine version that produced it, so comparisons across rule edits are free.
The verdicts are ranges, best → worst - the most important thing about this node. OK → RISK means "probably fine, worst case you lose some reach." RISK → BLOCK means "demoted, and possibly removed, depending on a factor the report names." Whenever best ≠ worst, a range driver spells out what would collapse it - a setting, a region, low sensor confidence. Severities: OK (no expected problem), RISK (reach demotion - the post stays up), BLOCK (removal on IG/TikTok, or For-You-Feed ineligibility), UNKNOWN (sensor unavailable or incompatible - your call). Hard blocks are reserved for real policy triggers; soft signals like framing, pose, mild exposure and suggestive text top out at RISK, because they demote rather than remove.
The inputs that matter
observations_json- theobservations_jsonoutput of PreFlight: Observe. It'sforceInput, so it's a socket, not a text box: you can't paste JSON into it.caption- the one field you fill in by hand, multiline, optional. Type the caption you're about to publish and it gets scanned with the in-image text.log_prediction- on by default, and you should leave it on. It appends the prediction to the feedback store and hands you back a record id.image(optional) - a pure pass-through so the node can sit inline instead of forcing you to branch the graph.
Outputs: report_json (the full structured report), summary (readable text, including record: <id>), record_id (empty string if logging is off or failed), and image. Wire summary into any text-display node, and the image into a Preview if you want the graph to keep flowing.
Install
Same pack as Observe, so you install it once:
cd ComfyUI/custom_nodes
git clone https://github.com/0xBeycan/ComfyUI-PreFlight
cd ComfyUI-PreFlight && pip install -r requirements.txt
Restart and the three nodes appear under PreFlight. This one has no dependencies of its own - the rules engine is pure standard library, so it works even if the Qwen-VL install is broken.
Where it goes wrong
Verdicts come back UNKNOWN. That's the fail-closed path, not a bug: either Observe handed over an error object (check its raw_response) or the observation's schema version is one the engine can't interpret.
You're treating OK → RISK as permission to publish. It isn't, and the pack says as much in its own README. Platform classifiers are black boxes, the thresholds here are informed hypotheses, and two identical images on two accounts get treated differently. A wide range means something you control is unknown - open the report JSON and read the range drivers.
You expected the rules to be right out of the box. They won't be. RISK thresholds especially need calibrating against your own results, which is what PreFlight: Outcome and calibrate.py exist for. Until you've logged real outcomes, treat this as a second opinion from someone who read the same policy pages you did.
Nothing here knows the image is AI-generated. The observation fields cover garments, exposure, framing, pose and text; there's no field for "synthetic". Platforms have moved toward labelling requirements for AI content, and no image sensor can see your labelling habits - don't read a clean verdict as cover for that.
One more: log_prediction writes a line on every queue. Cheap append-only JSONL, and it's the feature that makes the feedback loop work - but iterate on a caption thirty times and you'll have thirty records in the Outcome dropdown.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| observations_json | STRING | The observations_json output of PreFlight: Observe. | |
| caption | STRING | Optional caption to be published. Scanned for adult solicitation / links together with in-image text. | |
| log_prediction | BOOLEAN | true | Append this prediction to the feedback store so you can later record what the platform actually did. |
| imageopt | IMAGE | Optional pass-through so this node can sit inline in a workflow. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| report_json | STRING | — |
| summary | STRING | — |
| record_id | STRING | — |
| image | IMAGE | — |