# LinkedIn Text Ads decision, copy and test builder

Use this standalone prompt to decide whether LinkedIn Text Ads fit one offer, create claim-safe variants and produce a bounded test handoff.

## Current reference summary

Research date: 1 October 2026.

- LinkedIn Text Ads specifications: https://business.linkedin.com/advertise/ads/text-ads/specs
- LinkedIn Help: https://www.linkedin.com/help/lms/answer/a423705
- Image: fully decodable JPG or PNG, exactly 100 × 100 pixels, no more than 2,000,000 raw bytes. Sniff the MIME from the bytes and require it to match the declared MIME.
- Headline: 25 characters including spaces.
- Description: 75 characters including spaces.
- Count Unicode code points and UTF-16 code units. Enforce the larger count. Never truncate.
- Destination: HTTP(S). Help says 500 characters; the specifications page says 2,000. Use 500 as a conservative local limit. A URL from 501 to 2,000 needs native validation. More than 2,000 fails.
- Supported objectives named in current Help: brand awareness, website visits, engagement and website conversions.
- Text Ads are documented for desktop placement. Desktop audience mismatch returns Another format.
- If the offer needs a demonstration, long explanation, native lead form, personalization or multiple assets, compact-message fit is false and the decision is Another format.
- Current Help says Creative Manager access or higher is required to create the ad.

Local checks cannot prove target-account availability, native preview, asset acceptance, approval, delivery, auction outcome, conversion or qualified pipeline. Launch Ready requires a native receipt matching the accepted revision and fingerprint.

## Required JSON input

```json
{
  "offer": "",
  "buyer": "",
  "objective": "brand_awareness | website_visits | engagement | website_conversions | other | unknown",
  "desktop_audience_fit": true,
  "compact_message_fit": true,
  "approved_claims": [{"claim_id":"CLM-1","verbatim_text":"","source_ref":"","permission":"approved | denied | unknown"}],
  "sources": [{"source_id":"SRC-1","reference":"","captured_at":"","sha256_or_locator":"","permitted_use":""}],
  "image": {"asset_id":"","declared_mime":"image/png | image/jpeg","sniffed_mime":"image/png | image/jpeg | unknown","decoded_width":100,"decoded_height":100,"byte_length":0,"sha256":"","full_decode_valid":true},
  "destination_url": "https://",
  "audience": "",
  "audience_permission": "confirmed | denied | unknown",
  "learning_goal": "",
  "bid_basis": "cpc | cpm | unknown",
  "bid_basis_reason": "",
  "spend_ceiling": {"amount":null,"currency":"","period":""},
  "conversion_definition": "",
  "stop_conditions": [{"condition_id":"STOP-1","metric":"","operator":"lt | lte | eq | gte | gt | missing","threshold":null,"window":"","action":""}],
  "owner": "",
  "open_questions": [],
  "native_validation": {"state":"unknown | pending | verified | denied","evidence_ref":null,"approved_revision":null,"approved_fingerprint":null}
}
```

## Format decision

Evaluate format fit before production readiness. Use this exact precedence:

1. Unsupported supplied objective: `another_format`, `FIT-OBJECTIVE`.
2. Desktop fit false: `another_format`, `FIT-DESKTOP`.
3. Compact message fit false: `another_format`, `FIT-COMPACT`.
4. Missing offer: `hold`, `FIT-MISSING-OFFER`.
5. Missing buyer: `hold`, `FIT-MISSING-BUYER`.
6. Missing or unknown objective: `hold`, `FIT-MISSING-OBJECTIVE`.
7. Desktop fit null or unknown: `hold`, `FIT-DESKTOP-UNKNOWN`.
8. Compact message fit null or unknown: `hold`, `FIT-COMPACT-UNKNOWN`.
9. Otherwise: `use`, `FIT-USE`.

The image, destination, budget and owner control handoff readiness. They do not change format fit.

If the decision is not Use, readiness is Draft. If the decision is Use, evaluate claims, image, destination, audience, permission, learning goal, bid basis and reason, spend amount/currency/period, conversion, stop conditions and owner in that order. Return the first failing reason and one exact next action. All local checks passing returns Launch Hold. Only a matching native receipt returns Launch Ready.

## Copy rules

Create routes only when the decision is Use and approved claims exist. Hold and Another format records contain zero variants. A passing Use record needs three materially different routes. Each route needs:

- a unique variant ID and route label;
- literal headline and description;
- code-point, UTF-16 and enforced counts for both;
- approved claim IDs;
- a semantic-support result.

Different casing or punctuation does not create a new route. Do not add a number, result, feature, customer, audience fact or owner experience absent from the approved claims. If the claims cannot support three routes, preserve only the supported routes, return Draft with `READY-CLAIMS`, open `REQ-CLAIMS`, set semantic evaluation and final verdict false, and explain that three supported routes are required to pass. An incomplete record may contain zero to two variants; never pad it.

## Handoff rules

Preserve five sibling outcome rows: `delivery`, `click`, `site_action`, `crm_acceptance`, `commercial_outcome`. Each has `state`, `value` and `evidence_ref`. Before results exist, use literal `unknown`, `null`, `null`. Unknown never becomes zero, failure or success.

Preserve objective, audience, permission, destination, learning goal, bid basis and reason, spend ceiling, conversion, stop conditions, owner, outcomes, native validation and open questions.

## Missing-input behavior

Never guess. Open stable requests: `REQ-OFFER`, `REQ-BUYER`, `REQ-OBJECTIVE`, `REQ-DESKTOP-FIT`, `REQ-COMPACT-FIT`, `REQ-CLAIMS`, `REQ-IMAGE`, `REQ-DESTINATION`, `REQ-AUDIENCE`, `REQ-PERMISSION`, `REQ-LEARNING`, `REQ-BID`, `REQ-CEILING`, `REQ-CONVERSION`, `REQ-STOP`, `REQ-OWNER`, `REQ-NATIVE`.

For Hold, open only unresolved format-input requests. For Another format, the mismatch is resolved: do not open a request for that field, production readiness or native validation. For Use, open every failed readiness request and `REQ-NATIVE` until matching native evidence exists. The request array is the evaluator's exact unresolved set and may be empty.

An incomplete Draft may use empty `approved_claims`, `stop_conditions`, `sources`, `variants`, `requests` and `open_questions` arrays. A passing Use review requires approved claims, stop conditions, sources and three variants. `open_questions` may be empty in every state. Sources may be empty only when no claim cites one. Every supplied claim `source_ref` must resolve to one supplied source record; otherwise fail source traceability and, after the decision is Use, open `REQ-CLAIMS`.

## Output contract

Return a readable review with these exact non-empty headings:

1. Decision
2. Reason
3. Readiness
4. Variants
5. Test handoff
6. Outcome evidence
7. Open questions
8. Open requests
9. Sources
10. Review

The importer compares the readable text with one canonical renderer after converting CRLF to LF and trimming the whole document. Use level-one headings, exact labels, punctuation and spacing. Render Decision as `format_decision`. Render Reason as `format_reason_code: format_reason` followed by `next_action`. Render Readiness as `handoff_readiness — readiness_reason_code: readiness_reason`. Render Variants first as `N route in this record.` for one route or `N routes in this record.` otherwise. For each route add `## route_label`, `ID: variant_id`, the headline with `(enforced/25)`, the description with `(enforced/75)`, and `Claims: ` with IDs joined by comma and space. Render the complete test handoff as two-space-indented JSON. Render outcomes as `key: state`, questions one per line or `None`, requests as `request_id: next_action` or `None`, sources as `source_id: reference` or `None`, and Review as `Fingerprint: fingerprint` followed by `Final verdict: ` with the lowercase JSON boolean. Finish with `# Machine-readable record` and one two-space-indented fenced `json` object. Put one blank line between blocks and before each variant heading. Alternative bullets, tables or heading levels are not accepted.

Then return one fenced JSON object with:

```text
schema_version
contract_version
revision
fingerprint
inputs
evaluation
variants
test_handoff
sources
requests
review
```

Use `maestro.linkedin-text-ads.record.v1` and contract `0.2.0-evidence`.

Fingerprint canonical UTF-8 JSON containing the contract version and every meaning-bearing input. Sort object keys, remove insignificant whitespace and preserve array order. If you cannot calculate a hash or inspect the image bytes, say so and open the request. Never fabricate evidence.

The review has five booleans: `shape`, `semantic_evaluation`, `readable_output`, `source_traceability`, `limit_checks`. `final_verdict` is true only when all five are true and the approved revision and reviewed fingerprint match.

Use these exact state rules:

- Complete Use with exactly three distinct supported routes backed by approved sourced claims: `semantic_evaluation: true`. Compute the other predicates separately. If all five pass, bind the current revision and fingerprint and set `final_verdict: true`. Readiness may still be Draft or Launch Hold.
- Incomplete Use with zero to two routes or invalid claim support: `semantic_evaluation: false`, `final_verdict: false`, and both binding fields `null`.
- Hold: zero variants, `semantic_evaluation: false`, `final_verdict: false`, and both binding fields `null`.
- Another format: zero variants, `semantic_evaluation: false`, `final_verdict: false`, and both binding fields `null`.

For the last three states, preserve the actual shape, readable-output, source-traceability and limit-check results instead of forcing them false.

## Worked adaptation

For a fictional “B2B ad measurement review,” buyer “Demand generation lead,” claim “Review five outcome layers,” website-visits objective, confirmed desktop fit and confirmed compact-message fit, valid routes can use the buyer problem, the review template and the five-layer method.

If destination, permission, conversion or owner is missing, keep the format decision Use but return Draft readiness. If all local fields pass without matching native evidence, return Launch Hold.

## Exact portable record contract

The JSON below is the complete output schema. It is normative. Do not rename a key, add a key, change an enum, encode booleans as strings or move `sources` or `native_validation` into `inputs`. An incomplete Draft may use empty `approved_claims`, `stop_conditions`, `sources`, `variants`, `requests` and `open_questions` arrays. Empty claims, stop conditions or sources still fail the corresponding readiness or traceability check when the format decision is Use. For Use, zero to two variants means an incomplete review and exactly three distinct supported variants are required for `semantic_evaluation: true`. Hold and Another format require zero variants and always use `semantic_evaluation: false`. `open_questions` may be empty in any state. Every request row includes `request_id`, `field`, `state` and `next_action`.

For a Hold or Another format decision, include only requests that can resolve the current format decision. Do not open production-readiness or native-validation requests until the decision is Use. In particular, `FIT-COMPACT` may have no open request because Another format is the resolved decision; `FIT-COMPACT-UNKNOWN` opens only `REQ-COMPACT-FIT` when every earlier format input is present.

`review.approved_revision` and `review.reviewed_fingerprint` bind the five local review predicates to this record. They are separate from `test_handoff.native_validation`, which binds Campaign Manager evidence to a record for Launch Ready. A complete Use record sets `semantic_evaluation` true only when it has exactly three distinct supported routes backed by approved sourced claims. An incomplete Use record, Hold record or Another format record sets `semantic_evaluation` false, `final_verdict` false and both local binding fields to null. Compute shape, readable output, source traceability and limit checks independently; do not force those four predicates false because semantic evaluation is false. For a complete Use record, when all five predicates pass, set the local binding to this revision and fingerprint. Handoff readiness is independent: a locally passing Use review may still be Draft or Launch Hold.

### Exact readable Markdown transport

The readable text must use the exact renderer below. After converting CRLF to LF, the importer trims the whole readable document and compares it with this canonical rendering. Alternative bullets, tables, heading levels, labels, punctuation, spacing or field placement are not accepted.

- `# Decision`, then `format_decision`.
- `# Reason`, then one line `format_reason_code: format_reason`, then `next_action`.
- `# Readiness`, then one line `handoff_readiness — readiness_reason_code: readiness_reason` using an em dash.
- `# Variants`, then `N route in this record.` for one route or `N routes in this record.` otherwise. For each route add a blank line, `## route_label`, `ID: variant_id`, `headline (enforced/25)`, `description (enforced/75)`, and `Claims: ` followed by claim IDs joined with comma and space. The empty form is exactly `0 routes in this record.`
- `# Test handoff`, then the complete `test_handoff` object as JSON with two-space indentation.
- `# Outcome evidence`, then one line per outcome in object order as `key: state`.
- `# Open questions`, then each question on its own line, or `None`.
- `# Open requests`, then one line per request as `request_id: next_action`, or `None`.
- `# Sources`, then one line per source as `source_id: reference`, or `None`.
- `# Review`, then `Fingerprint: fingerprint`, then `Final verdict: ` with the lowercase JSON boolean.
- `# Machine-readable record`, then exactly one fenced `json` object containing the complete record with two-space indentation.

Put one blank line between blocks. Emit the listed lines consecutively inside each block except for the blank line before each variant heading.

The exact fingerprint input is the object `{"contract_version": record.contract_version, "inputs": record.inputs}`. Canonicalize recursively by sorting object keys lexicographically, preserving array order, encoding as UTF-8 JSON with no insignificant whitespace and hashing with SHA-256. Return 64 lowercase hexadecimal characters. Do not include sources, variants, evaluation, requests, test handoff or review outside `inputs` in the fingerprint.

For the complete supplied fixture, the canonical fingerprint is `1f9abf579c7cce93830aac553c65a09926ac80eb345394418a8521f63b549930`. If your value differs, stop and report the mismatch.

When a fixture supplies `attachments.image_bytes_base64`, decode it to raw bytes and verify the image receipt. The attachment is evidence only and never appears in the record. A metadata receipt without bytes or an explicitly trusted decoder receipt keeps image validation unresolved.

Stable format reason codes are `FIT-OBJECTIVE`, `FIT-DESKTOP`, `FIT-COMPACT`, `FIT-MISSING-OFFER`, `FIT-MISSING-BUYER`, `FIT-MISSING-OBJECTIVE`, `FIT-DESKTOP-UNKNOWN`, `FIT-COMPACT-UNKNOWN`, `FIT-USE`. Stable readiness codes, in order, are `READY-FORMAT`, `READY-CLAIMS`, `READY-IMAGE`, `READY-DESTINATION`, `READY-AUDIENCE`, `READY-PERMISSION`, `READY-LEARNING`, `READY-BID`, `READY-SPEND`, `READY-CONVERSION`, `READY-STOP`, `READY-OWNER`, `READY-LOCAL-PASS`, `READY-DESTINATION-NATIVE`, `READY-NATIVE`.

### JSON Schema

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://maestrogtm.com/schemas/linkedin-text-ad-record.v1.json",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version",
    "contract_version",
    "revision",
    "fingerprint",
    "inputs",
    "evaluation",
    "variants",
    "test_handoff",
    "sources",
    "requests",
    "review"
  ],
  "properties": {
    "schema_version": {
      "const": "maestro.linkedin-text-ads.record.v1"
    },
    "contract_version": {
      "type": "string",
      "minLength": 1
    },
    "revision": {
      "type": "integer",
      "minimum": 1
    },
    "fingerprint": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$"
    },
    "inputs": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "offer",
        "buyer",
        "objective",
        "desktop_audience_fit",
        "compact_message_fit",
        "approved_claims",
        "image",
        "destination_url",
        "audience",
        "audience_permission",
        "learning_goal",
        "bid_basis",
        "bid_basis_reason",
        "spend_ceiling",
        "conversion_definition",
        "stop_conditions",
        "owner",
        "open_questions"
      ],
      "properties": {
        "offer": {
          "type": "string"
        },
        "buyer": {
          "type": "string"
        },
        "objective": {
          "enum": [
            "brand_awareness",
            "website_visits",
            "engagement",
            "website_conversions",
            "other",
            "unknown"
          ]
        },
        "desktop_audience_fit": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "compact_message_fit": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "approved_claims": {
          "type": "array",
          "minItems": 0,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "claim_id",
              "verbatim_text",
              "source_ref",
              "permission"
            ],
            "properties": {
              "claim_id": {
                "type": "string",
                "minLength": 1
              },
              "verbatim_text": {
                "type": "string",
                "minLength": 1
              },
              "source_ref": {
                "type": "string",
                "minLength": 1
              },
              "permission": {
                "enum": [
                  "approved",
                  "denied",
                  "unknown"
                ]
              }
            }
          }
        },
        "image": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "asset_id",
            "declared_mime",
            "sniffed_mime",
            "decoded_width",
            "decoded_height",
            "byte_length",
            "sha256",
            "full_decode_valid"
          ],
          "properties": {
            "asset_id": {
              "type": "string",
              "minLength": 1
            },
            "declared_mime": {
              "enum": [
                "image/png",
                "image/jpeg"
              ]
            },
            "sniffed_mime": {
              "enum": [
                "image/png",
                "image/jpeg",
                "unknown"
              ]
            },
            "decoded_width": {
              "type": [
                "integer",
                "null"
              ]
            },
            "decoded_height": {
              "type": [
                "integer",
                "null"
              ]
            },
            "byte_length": {
              "type": "integer",
              "minimum": 0
            },
            "sha256": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$"
            },
            "full_decode_valid": {
              "type": "boolean"
            }
          }
        },
        "destination_url": {
          "type": "string"
        },
        "audience": {
          "type": "string"
        },
        "audience_permission": {
          "enum": [
            "confirmed",
            "denied",
            "unknown"
          ]
        },
        "learning_goal": {
          "type": "string"
        },
        "bid_basis": {
          "enum": [
            "cpc",
            "cpm",
            "unknown"
          ]
        },
        "bid_basis_reason": {
          "type": "string"
        },
        "spend_ceiling": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "amount",
            "currency",
            "period"
          ],
          "properties": {
            "amount": {
              "type": [
                "number",
                "null"
              ],
              "minimum": 0
            },
            "currency": {
              "type": "string"
            },
            "period": {
              "type": "string"
            }
          }
        },
        "conversion_definition": {
          "type": "string"
        },
        "stop_conditions": {
          "type": "array",
          "minItems": 0,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "condition_id",
              "metric",
              "operator",
              "threshold",
              "window",
              "action"
            ],
            "properties": {
              "condition_id": {
                "type": "string"
              },
              "metric": {
                "type": "string"
              },
              "operator": {
                "enum": [
                  "lt",
                  "lte",
                  "eq",
                  "gte",
                  "gt",
                  "missing"
                ]
              },
              "threshold": {
                "type": [
                  "number",
                  "string",
                  "null"
                ]
              },
              "window": {
                "type": "string"
              },
              "action": {
                "type": "string"
              }
            }
          }
        },
        "owner": {
          "type": "string"
        },
        "open_questions": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          }
        }
      }
    },
    "evaluation": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "format_decision",
        "format_reason_code",
        "format_reason",
        "handoff_readiness",
        "readiness_reason_code",
        "readiness_reason",
        "next_action"
      ],
      "properties": {
        "format_decision": {
          "enum": [
            "use",
            "hold",
            "another_format"
          ]
        },
        "format_reason_code": {
          "type": "string",
          "minLength": 1
        },
        "format_reason": {
          "type": "string",
          "minLength": 1
        },
        "handoff_readiness": {
          "enum": [
            "draft",
            "launch_hold",
            "launch_ready"
          ]
        },
        "readiness_reason_code": {
          "type": "string",
          "minLength": 1
        },
        "readiness_reason": {
          "type": "string",
          "minLength": 1
        },
        "next_action": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "variants": {
      "type": "array",
      "minItems": 0,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "variant_id",
          "route_label",
          "headline",
          "description",
          "headline_counts",
          "description_counts",
          "claim_source_ids",
          "semantic_support"
        ],
        "properties": {
          "variant_id": {
            "type": "string",
            "minLength": 1
          },
          "route_label": {
            "type": "string",
            "minLength": 1
          },
          "headline": {
            "type": "string",
            "minLength": 1
          },
          "description": {
            "type": "string",
            "minLength": 1
          },
          "headline_counts": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code_points",
              "utf16_units",
              "enforced"
            ],
            "properties": {
              "code_points": {
                "type": "integer",
                "minimum": 0
              },
              "utf16_units": {
                "type": "integer",
                "minimum": 0
              },
              "enforced": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "description_counts": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code_points",
              "utf16_units",
              "enforced"
            ],
            "properties": {
              "code_points": {
                "type": "integer",
                "minimum": 0
              },
              "utf16_units": {
                "type": "integer",
                "minimum": 0
              },
              "enforced": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "claim_source_ids": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "minLength": 1
            }
          },
          "semantic_support": {
            "enum": [
              "supported",
              "unsupported",
              "needs_review"
            ]
          }
        }
      }
    },
    "test_handoff": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "objective",
        "audience",
        "audience_permission",
        "destination_url",
        "learning_goal",
        "bid_basis",
        "bid_basis_reason",
        "spend_ceiling",
        "conversion_definition",
        "stop_conditions",
        "owner",
        "outcomes",
        "native_validation",
        "open_questions"
      ],
      "properties": {
        "objective": {
          "type": "string"
        },
        "audience": {
          "type": "string"
        },
        "audience_permission": {
          "type": "string"
        },
        "destination_url": {
          "type": "string"
        },
        "learning_goal": {
          "type": "string"
        },
        "bid_basis": {
          "type": "string"
        },
        "bid_basis_reason": {
          "type": "string"
        },
        "spend_ceiling": {
          "type": "object"
        },
        "conversion_definition": {
          "type": "string"
        },
        "stop_conditions": {
          "type": "array"
        },
        "owner": {
          "type": "string"
        },
        "outcomes": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "delivery",
            "click",
            "site_action",
            "crm_acceptance",
            "commercial_outcome"
          ],
          "properties": {
            "delivery": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "state",
                "value",
                "evidence_ref"
              ],
              "properties": {
                "state": {
                  "enum": [
                    "unknown",
                    "pending",
                    "verified",
                    "denied",
                    "not_applicable"
                  ]
                },
                "value": {
                  "type": [
                    "string",
                    "number",
                    "null"
                  ]
                },
                "evidence_ref": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "click": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "state",
                "value",
                "evidence_ref"
              ],
              "properties": {
                "state": {
                  "enum": [
                    "unknown",
                    "pending",
                    "verified",
                    "denied",
                    "not_applicable"
                  ]
                },
                "value": {
                  "type": [
                    "string",
                    "number",
                    "null"
                  ]
                },
                "evidence_ref": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "site_action": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "state",
                "value",
                "evidence_ref"
              ],
              "properties": {
                "state": {
                  "enum": [
                    "unknown",
                    "pending",
                    "verified",
                    "denied",
                    "not_applicable"
                  ]
                },
                "value": {
                  "type": [
                    "string",
                    "number",
                    "null"
                  ]
                },
                "evidence_ref": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "crm_acceptance": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "state",
                "value",
                "evidence_ref"
              ],
              "properties": {
                "state": {
                  "enum": [
                    "unknown",
                    "pending",
                    "verified",
                    "denied",
                    "not_applicable"
                  ]
                },
                "value": {
                  "type": [
                    "string",
                    "number",
                    "null"
                  ]
                },
                "evidence_ref": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "commercial_outcome": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "state",
                "value",
                "evidence_ref"
              ],
              "properties": {
                "state": {
                  "enum": [
                    "unknown",
                    "pending",
                    "verified",
                    "denied",
                    "not_applicable"
                  ]
                },
                "value": {
                  "type": [
                    "string",
                    "number",
                    "null"
                  ]
                },
                "evidence_ref": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        },
        "native_validation": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "state",
            "evidence_ref",
            "approved_revision",
            "approved_fingerprint"
          ],
          "properties": {
            "state": {
              "enum": [
                "unknown",
                "pending",
                "verified",
                "denied"
              ]
            },
            "evidence_ref": {
              "type": [
                "string",
                "null"
              ]
            },
            "approved_revision": {
              "type": [
                "integer",
                "null"
              ]
            },
            "approved_fingerprint": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        },
        "open_questions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "sources": {
      "type": "array",
      "minItems": 0,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "source_id",
          "reference",
          "captured_at",
          "sha256_or_locator",
          "permitted_use"
        ],
        "properties": {
          "source_id": {
            "type": "string",
            "minLength": 1
          },
          "reference": {
            "type": "string",
            "minLength": 1
          },
          "captured_at": {
            "type": "string",
            "minLength": 1
          },
          "sha256_or_locator": {
            "type": "string",
            "minLength": 1
          },
          "permitted_use": {
            "type": "string",
            "minLength": 1
          }
        }
      }
    },
    "requests": {
      "type": "array",
      "minItems": 0,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "request_id",
          "field",
          "state",
          "next_action"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "minLength": 1
          },
          "field": {
            "type": "string",
            "minLength": 1
          },
          "state": {
            "enum": [
              "open",
              "resolved",
              "not_applicable"
            ]
          },
          "next_action": {
            "type": "string",
            "minLength": 1
          }
        }
      }
    },
    "review": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "approved_revision",
        "reviewed_fingerprint",
        "shape",
        "semantic_evaluation",
        "readable_output",
        "source_traceability",
        "limit_checks",
        "final_verdict"
      ],
      "properties": {
        "approved_revision": {
          "type": [
            "integer",
            "null"
          ]
        },
        "reviewed_fingerprint": {
          "type": [
            "string",
            "null"
          ]
        },
        "shape": {
          "type": "boolean"
        },
        "semantic_evaluation": {
          "type": "boolean"
        },
        "readable_output": {
          "type": "boolean"
        },
        "source_traceability": {
          "type": "boolean"
        },
        "limit_checks": {
          "type": "boolean"
        },
        "final_verdict": {
          "type": "boolean"
        }
      }
    }
  }
}
```

### Decision and validation contract

```json
{
  "schema_version": "maestro.linkedin-text-ads.contract.v2",
  "contract_version": "0.2.0-evidence",
  "canonical_task": "format choice -> constrained variants -> bounded test -> production handoff",
  "authoritative_rule_order": [
    "current LinkedIn Text Ads Help",
    "current LinkedIn Text Ads specifications page",
    "Campaign Manager native validation",
    "attributed practitioner evidence",
    "editorial recommendation"
  ],
  "record_schema": {
    "path": "text-ad-record.schema.json",
    "sha256": "eb433e92304c0891d6ea08bd3366eb5410480476b6660f53f27779a5195ec0ac"
  },
  "fixture_corpus": {
    "path": "text-ad-fixtures.json",
    "sha256": "a55a839576b86d4d7a6a0a2158665e6ee1a35627a3f81ad62e23a501ba8769e2"
  },
  "character_count_policy": {
    "preserve_supplied_text": true,
    "normalization": "none",
    "reported_counts": [
      "Unicode code points",
      "UTF-16 code units"
    ],
    "local_enforcement": "Use the larger count; never truncate."
  },
  "image_validation_policy": {
    "steps": [
      "read raw bytes",
      "sniff MIME",
      "full decoder verification",
      "load decoded pixels",
      "read decoded dimensions",
      "compare byte length",
      "hash raw bytes"
    ],
    "pass": "full decode, declared/sniffed MIME agree, decoded 100x100, PNG/JPEG, <=2,000,000 bytes",
    "reject": "extension-only, metadata-only, corrupt, mismatch, wrong dimensions or over-cap"
  },
  "rules": [
    {
      "id": "TA-R01",
      "field": "image",
      "effect": "draft",
      "sources": [
        "linkedin-text-ads-specs",
        "linkedin-text-ads-help"
      ]
    },
    {
      "id": "TA-R02",
      "field": "headline",
      "effect": "variant_fail",
      "limit": 25,
      "sources": [
        "linkedin-text-ads-specs",
        "linkedin-text-ads-help"
      ]
    },
    {
      "id": "TA-R03",
      "field": "description",
      "effect": "variant_fail",
      "limit": 75,
      "sources": [
        "linkedin-text-ads-specs",
        "linkedin-text-ads-help"
      ]
    },
    {
      "id": "TA-R04",
      "field": "destination_url",
      "effect": "draft_or_native_check",
      "local_limit": 500,
      "native_check_through": 2000,
      "policy_type": "conservative_local_resolution_of_first_party_conflict",
      "sources": [
        "linkedin-text-ads-help",
        "linkedin-text-ads-specs"
      ]
    },
    {
      "id": "TA-R05",
      "field": "objective",
      "effect": "another_format",
      "allowed": [
        "brand_awareness",
        "website_visits",
        "engagement",
        "website_conversions"
      ],
      "sources": [
        "linkedin-text-ads-help"
      ]
    },
    {
      "id": "TA-R06",
      "field": "desktop_audience_fit",
      "effect": "another_format",
      "required": true,
      "sources": [
        "linkedin-text-ads-help"
      ]
    },
    {
      "id": "TA-R06B",
      "field": "compact_message_fit",
      "effect": "another_format",
      "required": true,
      "sources": [
        "reader_task"
      ]
    },
    {
      "id": "TA-R07",
      "field": "approved_claims",
      "effect": "draft",
      "requirement": "immutable IDs plus separate semantic support"
    },
    {
      "id": "TA-R08",
      "field": "audience_permission",
      "effect": "draft",
      "required": "confirmed"
    },
    {
      "id": "TA-R09",
      "field": "test_handoff",
      "effect": "draft",
      "requirement": "all schema fields"
    },
    {
      "id": "TA-R10",
      "field": "outcomes",
      "effect": "none_prelaunch",
      "requirement": "five typed siblings; Unknown remains literal"
    },
    {
      "id": "TA-R11",
      "field": "native_validation",
      "effect": "launch_hold",
      "requirement": "receipt matches revision and fingerprint"
    }
  ],
  "evaluation": {
    "format_precedence": [
      "FIT-OBJECTIVE",
      "FIT-DESKTOP",
      "FIT-COMPACT",
      "FIT-MISSING-OFFER",
      "FIT-MISSING-BUYER",
      "FIT-MISSING-OBJECTIVE",
      "FIT-DESKTOP-UNKNOWN",
      "FIT-COMPACT-UNKNOWN",
      "FIT-USE"
    ],
    "format_formula": "Unsupported objective -> another_format; desktop false -> another_format; compact-message fit false -> another_format; otherwise first missing fit input -> hold; otherwise use.",
    "readiness_precedence": [
      "READY-FORMAT",
      "READY-CLAIMS",
      "READY-IMAGE",
      "READY-DESTINATION",
      "READY-AUDIENCE",
      "READY-PERMISSION",
      "READY-LEARNING",
      "READY-BID",
      "READY-SPEND",
      "READY-CONVERSION",
      "READY-STOP",
      "READY-OWNER",
      "READY-LOCAL-PASS",
      "READY-NATIVE"
    ],
    "readiness_formula": "Format not use -> draft; first missing/invalid handoff input -> draft; local pass -> launch_hold; matching native receipt -> launch_ready.",
    "post_launch_boundary": "Outcome evidence is not a pre-launch requirement."
  },
  "collection_policy": {
    "schema_may_be_empty": [
      "inputs.approved_claims",
      "inputs.stop_conditions",
      "inputs.open_questions",
      "variants",
      "sources",
      "requests"
    ],
    "passing_use_requires_nonempty": [
      "inputs.approved_claims",
      "inputs.stop_conditions",
      "variants",
      "sources"
    ],
    "always_may_be_empty": [
      "inputs.open_questions",
      "requests"
    ],
    "source_rule": "Sources may be empty only when no supplied claim cites a source; every cited source_ref must resolve.",
    "claim_permission_rule": "Permission must be explicit. Omitted or blank permission is unknown and cannot support a passing Use record.",
    "stop_condition_rule": "Every stop condition needs an ID, metric, operator, window and action. lt, lte, eq, gte and gt need a nonblank threshold. The missing operator is threshold-free and requires threshold null."
  },
  "request_policy": {
    "exact_set": "Requests equal the evaluator's unresolved fields; do not add advisory rows.",
    "non_use": "Hold opens only unresolved format inputs. Another format opens no request for the resolved mismatch. Production-readiness and native-validation requests begin only after Use.",
    "empty": "An empty request array is valid when the evaluator finds no unresolved field, including a resolved Another format decision."
  },
  "variant_contract": {
    "schema_minimum": 0,
    "passing_minimum": 3,
    "non_use": "Hold and Another format contain zero variants.",
    "incomplete_behavior": "For Use, preserve zero to two supported routes, set semantic_evaluation and final_verdict false, readiness Draft with READY-CLAIMS, and open REQ-CLAIMS. Never pad.",
    "material_difference": "Different route label and claim emphasis; punctuation/casing alone fails",
    "claim_traceability": "Every claim ID resolves to an approved immutable claim; semantic support is separate from counts."
  },
  "review_contract": {
    "predicates": [
      "shape",
      "semantic_evaluation",
      "readable_output",
      "source_traceability",
      "limit_checks"
    ],
    "final_verdict_formula": "shape && semantic_evaluation && readable_output && source_traceability && limit_checks",
    "binding": "When final_verdict is true, approved_revision equals revision and reviewed_fingerprint equals fingerprint. When final_verdict is false, both binding fields are null.",
    "state_expectations": {
      "use_complete": "With exactly three distinct supported routes backed by approved sourced claims, semantic_evaluation is true. Compute the other four predicates independently. If all five are true, final_verdict is true and the local binding matches this record. Handoff readiness remains independent and may be Draft, Launch Hold or Launch Ready.",
      "use_incomplete": "With zero to two routes, or missing or invalid approved claim support, semantic_evaluation is false. final_verdict is false and both local binding fields are null. Preserve the actual values of shape, readable_output, source_traceability and limit_checks.",
      "hold": "Variants is empty. semantic_evaluation is false, final_verdict is false and both local binding fields are null. Preserve the actual values of the other four predicates.",
      "another_format": "Variants is empty. semantic_evaluation is false, final_verdict is false and both local binding fields are null. Preserve the actual values of the other four predicates."
    },
    "readable_labels": [
      "Decision",
      "Reason",
      "Readiness",
      "Variants",
      "Test handoff",
      "Outcome evidence",
      "Open questions",
      "Open requests",
      "Sources",
      "Review"
    ],
    "content_rule": "Use each required heading exactly once and in order. Every section has a non-heading content line and contains the required displayed values from the JSON record.",
    "markdown_transport": {
      "heading_rule": "Use the exact level-one headings and order in canonical_lines. Do not change heading levels, labels, punctuation, spacing or field placement.",
      "section_values": {
        "Decision": [
          "evaluation.format_decision"
        ],
        "Reason": [
          "evaluation.format_reason_code",
          "evaluation.format_reason",
          "evaluation.next_action"
        ],
        "Readiness": [
          "evaluation.handoff_readiness",
          "evaluation.readiness_reason_code",
          "evaluation.readiness_reason"
        ],
        "Variants": [
          "Use the exact variant block in canonical_lines. The first line is the route count, including exact text 0 routes in this record. when empty."
        ],
        "Test handoff": [
          "JSON.stringify(test_handoff, null, 2) semantics: UTF-8 JSON with two-space indentation and JavaScript property order"
        ],
        "Outcome evidence": [
          "Each outcome key and its state"
        ],
        "Open questions": [
          "Every inputs.open_questions string. When empty, include the exact text None."
        ],
        "Open requests": [
          "Every request_id and next_action. When empty, include the exact text None."
        ],
        "Sources": [
          "Every source_id and reference. When empty, include the exact text None."
        ],
        "Review": [
          "fingerprint",
          "the lowercase JSON boolean review.final_verdict"
        ]
      },
      "canonical_lines": [
        "# Decision; format_decision",
        "# Reason; format_reason_code: format_reason; next_action",
        "# Readiness; handoff_readiness — readiness_reason_code: readiness_reason",
        "# Variants; N route or N routes in this record.; then for each variant: ## route_label; ID: variant_id; headline (headline_counts.enforced/25); description (description_counts.enforced/75); Claims: claim IDs joined by comma and space",
        "# Test handoff; the complete test_handoff object as two-space-indented JSON",
        "# Outcome evidence; one line per outcome in object order as key: state",
        "# Open questions; each question on its own line, or None",
        "# Open requests; one line per request as request_id: next_action, or None",
        "# Sources; one line per source as source_id: reference, or None",
        "# Review; Fingerprint: fingerprint; Final verdict: lowercase JSON boolean",
        "# Machine-readable record; one fenced json object containing the complete record as two-space-indented JSON"
      ],
      "separator_rule": "Put one blank line between each listed block. Inside a block, emit the listed lines consecutively except for the blank line before each variant heading. Normalize CRLF to LF and ignore only leading and trailing whitespace around the whole readable document.",
      "equivalence": "No alternative bullets, tables, heading levels, labels or field placement are accepted. The readable text must equal this canonical rendering after CRLF-to-LF conversion and trimming the whole document.",
      "machine_record": "Return exactly one fenced json object under the exact heading # Machine-readable record. Use two-space indentation. The readable sections and fenced record describe the same record."
    }
  },
  "fingerprint_and_invalidation": {
    "canonicalization": "UTF-8 JSON, sorted object keys, no insignificant whitespace, array order preserved; binary identity is raw-byte SHA-256",
    "meaning_bearing_inputs": [
      "offer",
      "buyer",
      "objective",
      "desktop_audience_fit",
      "compact_message_fit",
      "approved_claims",
      "image",
      "destination_url",
      "audience",
      "audience_permission",
      "learning_goal",
      "bid_basis",
      "bid_basis_reason",
      "spend_ceiling",
      "conversion_definition",
      "stop_conditions",
      "owner",
      "open_questions"
    ],
    "behavior": "Change increments revision, preserves history, clears approval, regenerates variants/exports and returns readiness to draft or launch_hold."
  },
  "import_contract": {
    "transports": {
      "bare_json": "one object",
      "envelope_json": "exactly one record property",
      "markdown_fenced_json": "exactly one fenced JSON object"
    },
    "atomic_sequence": [
      "stage",
      "unwrap",
      "validate nested schema",
      "recompute counts and binary identity",
      "evaluate semantics/sources",
      "render readable output",
      "evaluate all predicates",
      "compare revision/fingerprint",
      "commit once"
    ],
    "failure_behavior": "Reject before commit; accepted object, approval and rendered output remain byte-identical."
  },
  "stable_request_ids": {
    "offer": "REQ-OFFER",
    "buyer": "REQ-BUYER",
    "objective": "REQ-OBJECTIVE",
    "desktop_audience_fit": "REQ-DESKTOP-FIT",
    "compact_message_fit": "REQ-COMPACT-FIT",
    "approved_claims": "REQ-CLAIMS",
    "image": "REQ-IMAGE",
    "destination_url": "REQ-DESTINATION",
    "audience": "REQ-AUDIENCE",
    "audience_permission": "REQ-PERMISSION",
    "learning_goal": "REQ-LEARNING",
    "bid_basis": "REQ-BID",
    "spend_ceiling": "REQ-CEILING",
    "conversion_definition": "REQ-CONVERSION",
    "stop_conditions": "REQ-STOP",
    "owner": "REQ-OWNER",
    "native_validation": "REQ-NATIVE"
  },
  "scope_boundary": {
    "local_can_prove": [
      "field presence",
      "copy counts",
      "full decoded image bytes",
      "URL syntax",
      "contract consistency",
      "export round trip"
    ],
    "native_only": [
      "account permissions",
      "target-account objective availability",
      "asset acceptance",
      "native preview",
      "approval",
      "delivery",
      "auction result",
      "conversion",
      "qualified outcome"
    ]
  }
}
```


Now process the supplied JSON object and any named attachment.
