You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A negative-lookbehind literal cannot be carried in an issue/PR body — the ! is deleted from (? + less-than + ! + [, and AGENTS.md's sanitizer clause names only less-than plus a letter #9621
Found while implementing #9610 (PR #9618). ⛔ Filed rather than fixed there: that card is a regex fix in one gate script, and this is a change to AGENTS.md's binding sanitizer clause, plus a second measured instance of the read-layer family in #9557.
⚠️ This body deliberately avoids the two token shapes it is about, so that it stays readable through every channel. Where it must name them it spells them out in words.
What happened
#9610's "Suggested fix" proposes a negative lookbehind. As it reads back today — through the GitHub MCP tool and through the rendered web page — the literal is missing its !:
what the card shows: (? LT [\w$.'"`]) -> SyntaxError: Invalid capture group name
what the author wrote: (? LT ! [\w$.'"`]) -> compiles
(LT = a less-than sign; see the note above.) V8 reads a less-than immediately after (? as the opener of a named group, so the form that survives storage does not compile at all. I was one step from filing that as a defect in the card.
It is not one. The card's prose names "a negative lookbehind" and reasons from the property only the negative form has ("satisfied at position 0"), so the author wrote the !. The same deletion then happened to me: PR #9618's first body revision carried the real literal in three places and came back with all three ! gone.
⇒ Two independent authors, same construct, same deletion.
Measured — and narrower than "less-than plus bang"
Six probe lines were authored into this card and read back off the rendered page. The transcription is its own control: it preserved a ! in one line and dropped it in another.
probe
authored
read back
verdict
PROBE-1
A less-than !B
A<!B
survives
PROBE-2
A less-than =B
A<=B
survives
PROBE-3
A less-than -B
A<-B
survives
PROBE-4
A less-than xB
A<xB
survives
PROBE-5
A less-than B
A< B
survives
PROBE-6
(? less-than [\w$])
(?<[\w$])
⛔ ! deleted
⇒ The trigger is not a bare less-than followed by ! — PROBE-1 keeps it. What is destroyed is less-than, !, then [ — the markup-declaration/CDATA opener. That is exactly and only the shape of a negative lookbehind over a character class, which is the single most common way anyone in this repo would write one.
⚠️ PROBE-4 surviving is worth noting separately: it contradicts a plain reading of the documented "less-than followed by a letter is stripped as a tag" rule. Inside a code fence, at least, a less-than plus letter came back intact. The documented clause may be describing prose position only, or may be imprecise.
A second, different mutation in the same card
The first revision of this issue contained the doctype opener (less-than, !, D, ...) in one prose sentence. Reading the card back through the GitHub MCP tool truncated the body at that token — everything after it was gone, while the web page showed the whole card.
That is #9557's finding (MCP truncates a body at a literal script-tag token) reproduced on a different token. ⇒ Deletion and truncation are two different behaviours in two different layers, and a seat can hit either.
Why this is worth a card rather than a shrug
⚠️It is silent and it lands in the load-bearing sentence. The deletion leaves text that still reads like code and no longer means what the author wrote. Here it converted a correct proposal into an apparent syntax error, and the only reason it was caught is that the implementer tried to compile it before believing it.
⚠️AGENTS.md documents a neighbouring case, and its rule does not cover this one. The sanitizer clause names a less-than followed by a letter. Following that rule exactly still loses a negative lookbehind, and PROBE-4 suggests the stated rule is not even the one in force inside code fences.
⭐ The os-dev-report marker is the same opener. The dev contract already carries a measured warning that the marker is eaten at rest and prescribes a plain-text fallback. That clause and this one are describing the same family, and only the marker's instance is written down.
Suggested resolution
Replace the "less-than followed by a letter" clause with what is measured: name the markup-declaration opener (less-than, !, [) as the destructive one, and keep the marker fallback as its named instance.
State the guidance that is missing today and is what a seat actually needs: a load-bearing literal containing a less-than must not be trusted to a GitHub body. Put it in the diff, a file, or a fenced block whose exact bytes do not matter, and reference it.
Found while implementing #9610 (PR #9618). ⛔ Filed rather than fixed there: that card is a regex fix in one gate script, and this is a change to
AGENTS.md's binding sanitizer clause, plus a second measured instance of the read-layer family in #9557.What happened
#9610's "Suggested fix" proposes a negative lookbehind. As it reads back today — through the GitHub MCP tool and through the rendered web page — the literal is missing its
!:(
LT= a less-than sign; see the note above.) V8 reads a less-than immediately after(?as the opener of a named group, so the form that survives storage does not compile at all. I was one step from filing that as a defect in the card.It is not one. The card's prose names "a negative lookbehind" and reasons from the property only the negative form has ("satisfied at position 0"), so the author wrote the
!. The same deletion then happened to me: PR #9618's first body revision carried the real literal in three places and came back with all three!gone.⇒ Two independent authors, same construct, same deletion.
Measured — and narrower than "less-than plus bang"
Six probe lines were authored into this card and read back off the rendered page. The transcription is its own control: it preserved a
!in one line and dropped it in another.Aless-than!BA<!BAless-than=BA<=BAless-than-BA<-BAless-thanxBA<xBAless-thanBA< B(?less-than[\w$])(?<[\w$])!deleted⇒ The trigger is not a bare less-than followed by
!— PROBE-1 keeps it. What is destroyed is less-than,!, then[— the markup-declaration/CDATA opener. That is exactly and only the shape of a negative lookbehind over a character class, which is the single most common way anyone in this repo would write one.A second, different mutation in the same card
The first revision of this issue contained the doctype opener (less-than,
!,D, ...) in one prose sentence. Reading the card back through the GitHub MCP tool truncated the body at that token — everything after it was gone, while the web page showed the whole card.That is #9557's finding (MCP truncates a body at a literal script-tag token) reproduced on a different token. ⇒ Deletion and truncation are two different behaviours in two different layers, and a seat can hit either.
Why this is worth a card rather than a shrug
AGENTS.mddocuments a neighbouring case, and its rule does not cover this one. The sanitizer clause names a less-than followed by a letter. Following that rule exactly still loses a negative lookbehind, and PROBE-4 suggests the stated rule is not even the one in force inside code fences.⭐ The
os-dev-reportmarker is the same opener. The dev contract already carries a measured warning that the marker is eaten at rest and prescribes a plain-text fallback. That clause and this one are describing the same family, and only the marker's instance is written down.Suggested resolution
!,[) as the destructive one, and keep the marker fallback as its named instance.<scripttoken — the card reads fine on the web and short through the API #9557 (read layer) or stands alone (storage/render layer). The probe above does not separate storage from render — a byte-exact authenticated REST read would. The direct route is unavailable from a dev session:api.github.comreturnsGitHub access is not enabled for this session. An org admin must connect the Claude GitHub App for this organization.Refs: #9610 (where it surfaced) · PR #9618 · #9557 (read-layer truncation) · #9031 (entities are a read artifact)