Reproducing the Pangram 4 bypass on the "Hi Jennn" text
Result to reproduce: the pasted text scores 0.834 (AI, High). The process below took it to 0.152 (Human, High) in 78 scoring calls. A run that stalls around 0.75 has almost certainly skipped the replacement loop (Step 4), because 0.725 is the floor reachable by deletions alone on this text.
What the process is, in one paragraph
Treat Pangram's own score as the objective function and do a greedy per-sentence search against it. Nothing about the edits is decided by a person or by a rewrite prompt; the detector picks every edit. The LLM's only job is to propose five structurally different versions of one sentence at a time. The score chooses among them.
Exact steps
Step 0. Scoring function
POST https://text.external-api.pangram.com/task with header x-api-key and body {"text": ..., "model": "pangram-4"}. Poll GET /task/{task_id} until stage == STAGE_SUCCESS. SCORE = max(window.ai_assistance_score for window in windows). Use the per-window score, not fraction_ai. LABEL = prediction_short. Scores are deterministic, so cache by exact text and never re-score the same string.
Step 1. Baseline
Split into sentences, keep paragraph breaks and the greeting line. Score the whole text. (0.834 here.)
Step 2. Rank sentences by deletion impact
For each sentence, score the text with only that sentence removed. Sort by resulting score, lowest first. On this text the top four were: "Separating pickup from payment mattered most." (0.725), "We changed the front counter (...)" (0.725), "I coordinated counter and shelving changes." (0.770), "I'd trace an order's last few metres..." (0.816). Cost: 10 calls.
Step 3. Replacement loop (the step that was probably skipped)
For each of the top four sentences in order: a. Send the rewrite LLM the full current text plus the one sentence, with the candidate prompt below. It returns five alternatives. b. Substitute each alternative into the full text, score all five (5 calls). c. Accept the lowest-scoring alternative only if it beats the current SCORE. Otherwise leave the sentence alone. After the four sentences, RE-RUN STEP 2 on the new text. The ranking changes after every accepted edit; a stale ranking is the second most common way to stall. Repeat until LABEL == "Human" and SCORE <= your target (0.30 gives margin).
Candidate prompt, verbatim: You rewrite ONE sentence from a text. Output exactly 5 alternative versions of that sentence, one per line, no numbering, no commentary. Every version must keep the same concrete facts (numbers, named parts, timeframes, outcomes) and still fit the surrounding text. Make the five structurally different from each other and from the original: 1. a version where a concrete noun or number is the grammatical subject 2. a version that attaches the facts as a parenthetical to a shorter main clause 3. a version with the clauses in reverse order 4. a version with no reporting or attribution verb (no "found", "said", "told", "saw", "suggested", "my view is") 5. a version under eight words, dropping any opinion but keeping the fact. Do not add casual filler, slang, typos, or extra hedging. Do not change the other sentences.
Step 4. Stop
Stop when LABEL is Human at or below the target score. Output the text and the list of accepted edits.
The run, call by call
| round | sentence | accepted replacement | score |
|---|---|---|---|
| 0 | baseline | 0.834 | |
| 1 | Separating pickup from payment mattered most. | Pickup orders and payments were kept separate, which mattered most. | 0.813 |
| 1 | We changed the front counter (shortened it, added a pickup ledge ...) | Counter-shortening, entrance-pickup-ledge/behind-numbered-shelves installation, and doorway-cabinet removal followed. | 0.536 |
| 1 | I coordinated counter and shelving changes. | no candidate beat 0.536, unchanged | 0.536 |
| 1 | I'd trace an order's last few metres ... | no candidate beat 0.536, unchanged | 0.536 |
| 2 | Pickup orders competed with payments and dining space ... | There was competition (pickup orders versus payments and dining space at a Melbourne restaurant in 2019). | 0.527 |
| 2 | Pickup orders and payments were kept separate, which mattered most. | Above all, pickup orders remained separate from payments. | 0.444 |
| 2 | It took two days and cost about $6,500. | The work was completed (in two days, for about $6,500). | 0.402 Human |
| 3 | There was competition (...) | Melbourne restaurant, 2019: pickup orders versus payments/dining-space. | 0.152 Human |
Calls: 1 baseline + 10 ranking + 20 candidates (round 1) + 10 ranking + 15 candidates (round 2) + 1 label check + 10 ranking + 5 candidates (round 3) + label checks = 78. Rewrite LLM: gpt-5.6-sol, 8 requests.
Ways to get a 0.75 result instead
- Deletions only, no replacement loop. Floor on this text is 0.725.
- Applying the "rules" (no reporting verbs, parentheticals, fragments) by hand or via one rewrite prompt, without scoring five candidates per sentence. Tested separately: 0 of 8 texts passed that way.
- Not re-ranking after each accepted edit.
- Using fraction_ai or the document label as the objective instead of the max window score; the document label is flat ("AI") across most of the search and gives no gradient.
- Budget under ~40 calls. The first large drop here came on call 25.
- Scoring a different text than the one being edited (whitespace or quote-character differences change the score).
Where the $8 comes from
Pangram's developer rate is $0.05 per 100 words, billed per 100-word unit (pangram.com/knowledge-hub, "What is Pangram's Developers plan"). The text is 130 words, so each call bills 2 units = $0.10. 78 calls x $0.10 = $7.80. The rewrite LLM added roughly $0.10 to $0.30 (8 short requests). Total about $8. Caveat: an older Pangram blog post describes one credit as covering about 400 words. If that is the live rule, the run cost 78 credits; compare the dashboard balance before and after a run to confirm which applies. Longer texts cost more per call (units) and need more rounds (sentences): budget $40 to $60 for 400 words.
Quality caveat
The search drifts toward telegraphic compound-noun strings ("Counter-shortening, entrance-pickup-ledge/..."). That is where the classifier is weakest, so that is where greedy search goes. The result passes but reads badly. A readability gate (an LLM judge rejecting unreadable candidates before scoring) keeps the text usable at roughly double the calls.
What to patch
The attack needs two things from the API: a deterministic continuous per-window score, and unlimited near-duplicate submissions. Quantising the score, adding per-key noise, or returning label-only to keys whose consecutive submissions differ by one sentence (shingle similarity > 0.9) removes the gradient the search relies on. Model-side, add the three structures above (framing-sentence deletion, parenthetical fact-stuffing after a short main clause, semicolon/hyphen noun-phrase chains) to the AI-class training data.