Skip to content

Commit 499f7f9

Browse files
claude[bot]claude
andauthored
fix(pm): post-stamped refuses a token it cannot render (#18286)
Fixes #18284 ## The defect `scripts/pm/post-stamped.mjs` recognised its two tokens with `QUOTED_TOKEN_RE` (`{{WAS:([^{}]*)}}`) and caught the rest with a post-substitution leftover scan over `ANY_TOKEN_RE` (`{{[^{}]*}}`). Both spell their payload `[^{}]*`, so a token-shaped opener whose payload carries a **brace**, or one that never closes at all, matched neither: it was not substituted, because nothing recognised it, and it was not refused, because the leftover scan could not see it. It was copied to the board verbatim. The filed reading is the seat's own artefact: a quoted slot was filled from a shell variable, the read failed, and the variable held a multi-line Node dump — which carries braces. Reproduced here on the unpatched tool at `fe0ae5c1`: ``` $ node scripts/pm/post-stamped.mjs --dry-run --comment=18284 --file=dump.md ; echo "EXIT=$?" post-stamped: DRY RUN — nothing was written. 0 token(s) substituted with `2026-09-15T08:18Z`, 0 quoted stamp(s) rendered verbatim. Target would be #18284 (comment). EXIT=0 ``` …and its stdout was the body it would have written, opener, dump and closer intact. Same fixture after the patch, `EXIT=2`, nothing on stdout: ``` post-stamped: REFUSED — 1 double-brace opener(s) in this body are not tokens this tool can render. Nothing was written. 1. [brace-in-payload] a brace inside the payload, so no token ends here — `{{WAS:[eval]:1\nJSON.parse(process.env.LANDED).mergedAt\n …` ``` ## What changed The check moved **ahead of substitution** and changed what it walks: not the tokens a regex happens to match, but every `{{` in the body, positionally — because the defect is precisely an opener no regex in the file matches, so a scan built out of those same regexes would walk past it again. Each opener must be `{{NOW}}` or a `{{WAS:…}}` whose payload is brace-free and closed. Four shapes are refused and named: `unknown-token-name`, `unclosed-opener`, `brace-in-payload`, `nested-opener`. The refusal prints the offending span clipped to 60 bytes with control characters escaped, so a payload that arrived from a shell read gone wrong stays readable; the same renderer is now applied to the existing `quoted-not-a-stamp` detail, which used to inline a raw multi-line dump into a numbered row. The scan judges **shape and stops**. Whether an admitted payload is an instant, and one the clock has reached, stays with `stampRefusals` — two places deciding "what is a quoted stamp" is two spellings of one decision. What the scan gives that rule is the thing it could not previously assume: that `maskQuotedStamps` consumed every opener, so the bare-stamp scan underneath is reading prose and not the inside of a token nobody could parse. That ordering is pinned: an unclosed opener on the opening line is reported as the opener it is, not as the positional refusal the unmasked payload would otherwise raise. The post-substitution leftover check is **gone** rather than kept beside the scan: after the scan every opener is consumed and the two substituted stamps carry no braces, so it could never fire, and a check that cannot fire is a check nobody maintains. Its `kind` (`unknown-token`), its exit code and the two sentences callers read are preserved on the new refusal. **No accepted form is narrowed.** The forms the tool took before — `{{NOW}}` exactly; `{{WAS:…}}` with a payload that is one `protocolStamps` match and nothing else, minute- or seconds-grained, surrounding whitespace tolerated — all still clear the scan, each pinned by a case. A bare stamp in prose is still not an opener's business, and a token inside backticks is **still substituted**: there has never been an escape form and the scan does not invent one. `--dry-run` and the live write take the same refusal, because both run through `renderBody`. The DRY RUN line, the read-back delta note, the `--ack-through` rule and the footer policy are untouched. ## Verification - Self-test **117 → 152** cases, **8 → 9** batteries; `SELF_TEST_BATTERY_FLOOR` raised 8 → 9 so a deleted battery is still caught. New battery: *the opener scan: every `{{` is a token this tool renders, or the body is refused* (35 cases) — the filed repro, a multi-line payload, an unknown token name, an unclosed opener, nested and doubled openers, the valid-pair control, the no-narrowing controls, the no-escape-hatch controls, and the span renderer. - Reverse verification by ablation from the committed state: the base blob was checked out over the file, its presence proved by `git hash-object` against `fe0ae5c1:scripts/pm/post-stamped.mjs` (and `grep -c unrecognisedOpeners` → 0), the fixture run, then `git checkout HEAD --` restored and `git diff HEAD` proved empty. Both readings are quoted above. - All 32 commands from `node scripts/pm/dispatch-gates.mjs --commands` exit 0, plus `node scripts/pm/post-stamped.mjs --self-test`, `node scripts/check-self-test-wired.mjs` and ESLint on the file. - No changeset: nothing published moves. `scripts/pm/**` is not in any package's `files[]`. ## Acceptance notes Noted, not filed — nothing in this PR's path touches them and no queued card covers the file: - The tool's usage text and header describe the quoted payload as `YYYY-MM-DDThh:mmZ`, while the shape actually accepted is `PROTOCOL_STAMP_RE`, whose seconds group is optional. The seconds grain is deliberate and pinned by an existing case; only the prose is narrower than the contract. Documentation nit, left alone rather than widened in a fix PR. One reproducible defect found while reading the payload rules is reported in the terminal report for the seat to file, with dedupe words: a quoted payload that matches the stamp *shape* but names an impossible date is accepted and rendered verbatim, because `stampSpan` returns `null` for it and `stampIsFuture` reads `null` as "not future". It is a different failure mode from this card's — rendered-but-unvalidated rather than neither-rendered-nor-refused — so it is not fixed here. --- _Generated by [Claude Code](https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9ed3f16 commit 499f7f9

1 file changed

Lines changed: 241 additions & 19 deletions

File tree

‎scripts/pm/post-stamped.mjs‎

Lines changed: 241 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@
5050
* QUOTED a `{{WAS:…}}` value is not one stamp and nothing else, or names
5151
* an instant LATER than the clock this act holds. See the
5252
* direction section below.
53-
* UNKNOWN a `{{…}}` token survives substitution. A mistyped `{{now}}`
54-
* would otherwise post literally AND leave the artefact
55-
* unstamped, which is the quiet direction.
53+
* UNKNOWN a double-brace opener that is not one of the two tokens. A
54+
* mistyped `{{now}}` would otherwise post literally AND leave the
55+
* artefact unstamped, which is the quiet direction. See the
56+
* opener scan below for what "not one of the two" now covers.
5657
*
5758
* ⛔ The positional refusal is NOT the mixed one widened for tidiness. Mixed
5859
* alone leaves the estimated stamp fully spellable — a seat that never types
@@ -93,6 +94,44 @@
9394
* something else, and refusing it would push seats back onto the channel this
9495
* tool exists to replace.
9596
*
97+
* ## EVERY `{{` is a token this tool can render, or the body is refused (#18284)
98+
*
99+
* The UNKNOWN refusal above used to run AFTER substitution, over whatever
100+
* `{{…}}` the two regexes had left behind. Both of those regexes spell their
101+
* payload `[^{}]*`, so a token-shaped opener whose payload carries a BRACE, or
102+
* that never closes at all, matched neither one — it was not substituted,
103+
* because nothing recognised it, and it was not refused either, because the
104+
* leftover scan could not see it. It was copied to the board verbatim.
105+
*
106+
* That is not a hypothetical. A seat filled a `{{WAS:…}}` slot from a shell
107+
* variable, the read failed, and the variable held a multi-line Node dump —
108+
* which carries braces. `--dry-run` printed its DRY RUN line reporting "0
109+
* token(s) substituted, 0 quoted stamp(s) rendered verbatim", the live write
110+
* printed 「comment posted」, and the stored comment carried the opener, the
111+
* dump and the closer. A leftover double-brace opener in a stored artefact is
112+
* never intended by anyone.
113+
*
114+
* So the check moved AHEAD of substitution and changed what it walks: not the
115+
* tokens a regex happens to match, but every `{{` in the body, each of which
116+
* must be `{{NOW}}` or a `{{WAS:…}}` whose payload is brace-free and closed.
117+
* Four shapes are refused there — an unknown token NAME, an opener with no
118+
* closer, a brace inside the payload, a second opener before the first closes
119+
* — and the refusal prints the offending span so the typo is findable.
120+
*
121+
* ⛔ The scan judges the SHAPE and stops. Whether an admitted `{{WAS:…}}`
122+
* payload is really an instant, and one the clock has reached, stays with
123+
* `stampRefusals` — two places deciding "what is a quoted stamp" is two
124+
* spellings of one decision, which is the defect this file spends its length
125+
* avoiding. What the scan guarantees `stampRefusals` is the thing that rule
126+
* could not previously assume: that `maskQuotedStamps` consumed every opener,
127+
* so the BARE-stamp scan underneath it is reading prose and not the inside of a
128+
* token nobody could parse.
129+
*
130+
* ⛔ And the scan opens no escape hatch. There has never been one — no
131+
* backslash form, no entity form — and a token inside backticks is still
132+
* substituted, because a fence is a rendering instruction and the substitution
133+
* runs on bytes. A body that must SHOW a token spells it some other way.
134+
*
96135
* ## ⚖️ Why this ACTS by default, where `sweep-closed-cards.mjs` dry-runs
97136
*
98137
* Its sibling next door defaults to a dry run and needs `--write`, because it
@@ -201,10 +240,132 @@ export const STAMP_TOKEN = '{{NOW}}';
201240
*/
202241
export const QUOTED_TOKEN_RE = /\{\{WAS:([^{}]*)\}\}/;
203242

204-
/** Any `{{…}}` token, used to catch the ones substitution did not consume. */
243+
/**
244+
* Any well-formed `{{…}}` token — an opener, a brace-free payload, a closer.
245+
* Read by the opener scan to tell a token with an unknown NAME (`{{now}}`, and
246+
* the rest of the typo family) from one that does not close at all.
247+
*/
205248
export const ANY_TOKEN_RE = /\{\{[^{}]*\}\}/;
206249

207250
const globalOf = (re) => new RegExp(re.source, 'g');
251+
const anchoredOf = (re) => new RegExp(`^${re.source}`);
252+
253+
/** The double-brace pair every token in this contract is built out of. */
254+
const TOKEN_OPENER = '{{';
255+
const TOKEN_CLOSER = '}}';
256+
257+
/** How much of an offending span a refusal prints. */
258+
export const SPAN_BYTES = 60;
259+
260+
/**
261+
* The C0 controls that have a spelling everybody reads; the rest get `\xNN`.
262+
* ⛔ Written as escapes rather than as the bytes themselves — a raw control
263+
* byte in a source file is what `check:nul-bytes` exists to keep out.
264+
*/
265+
const CONTROL_ESCAPES = Object.freeze({ '\n': '\\n', '\r': '\\r', '\t': '\\t' });
266+
const CONTROL_RE = /[\u0000-\u001f\u007f]/gu;
267+
268+
/**
269+
* An offending span as a refusal can print it: the first `SPAN_BYTES` BYTES,
270+
* every control character spelled out, one line.
271+
*
272+
* Bytes rather than characters because the span this exists for is a shell
273+
* variable that went wrong — a Node dump, a stack trace, a whole file — and a
274+
* refusal that inlines it raw stops being readable at exactly the moment a
275+
* reader needs it. The cut is taken on the byte, then a half-character left at
276+
* the edge is dropped rather than printed as a replacement glyph.
277+
*/
278+
export function offendingSpan(text, limit = SPAN_BYTES) {
279+
const buf = Buffer.from(String(text ?? ''), 'utf8');
280+
const clipped = buf.byteLength > limit;
281+
const head = clipped
282+
? buf.subarray(0, limit).toString('utf8').replace(/\uFFFD+$/u, '')
283+
: buf.toString('utf8');
284+
const shown = head.replace(CONTROL_RE, (ch) => CONTROL_ESCAPES[ch] ?? `\\x${ch.codePointAt(0).toString(16).padStart(2, '0')}`);
285+
return `${shown}${clipped ? '…' : ''}`;
286+
}
287+
288+
/** Why an opener is not a token, in the words the refusal prints. */
289+
export const OPENER_REASONS = Object.freeze({
290+
'unknown-token-name': 'a well-formed token, but not one this tool knows',
291+
'unclosed-opener': 'an opener with no closer after it anywhere in the body',
292+
'brace-in-payload': 'a brace inside the payload, so no token ends here',
293+
'nested-opener': 'a second opener before this one is closed',
294+
});
295+
296+
/**
297+
* Every `{{` in this text that is not one of the two tokens, in the order a
298+
* reader meets them. An empty array is a body whose every opener renders.
299+
*
300+
* The walk is positional rather than a regex sweep on purpose: the defect this
301+
* closes is an opener NO regex in this file matches, so a scan built out of
302+
* those same regexes would walk straight past it again. What the regexes are
303+
* still used for is recognition at a known position — anchored, so the one
304+
* definition of "a quoted token" serves both the scan and the substitution.
305+
*/
306+
export function unrecognisedOpeners(text) {
307+
const raw = String(text ?? '');
308+
const quotedHere = anchoredOf(QUOTED_TOKEN_RE);
309+
const anyHere = anchoredOf(ANY_TOKEN_RE);
310+
const out = [];
311+
let i = 0;
312+
for (;;) {
313+
const at = raw.indexOf(TOKEN_OPENER, i);
314+
if (at === -1) return out;
315+
const rest = raw.slice(at);
316+
317+
if (rest.startsWith(STAMP_TOKEN)) {
318+
i = at + STAMP_TOKEN.length;
319+
continue;
320+
}
321+
const quoted = quotedHere.exec(rest);
322+
if (quoted) {
323+
// A recognised SHAPE. Whether the payload is an instant the clock has
324+
// reached is `stampRefusals`' rule, not this one.
325+
i = at + quoted[0].length;
326+
continue;
327+
}
328+
const wellFormed = anyHere.exec(rest);
329+
if (wellFormed) {
330+
out.push({ kind: 'unknown-token-name', at, span: wellFormed[0] });
331+
i = at + wellFormed[0].length;
332+
continue;
333+
}
334+
335+
const close = raw.indexOf(TOKEN_CLOSER, at + TOKEN_OPENER.length);
336+
if (close === -1) {
337+
// Nothing after an unclosed opener can be resynchronised on: every later
338+
// `{{` is arguably inside it. One refusal, naming where it starts.
339+
out.push({ kind: 'unclosed-opener', at, span: rest });
340+
return out;
341+
}
342+
const span = raw.slice(at, close + TOKEN_CLOSER.length);
343+
out.push({
344+
kind: span.slice(TOKEN_OPENER.length).includes(TOKEN_OPENER) ? 'nested-opener' : 'brace-in-payload',
345+
at,
346+
span,
347+
});
348+
i = close + TOKEN_CLOSER.length;
349+
}
350+
}
351+
352+
/** The refusal a caller reads when an opener is not a token this tool renders. */
353+
export function unrecognisedOpenerText(problems) {
354+
const rows = (problems ?? []).map(
355+
(p, i) => ` ${i + 1}. [${p.kind}] ${OPENER_REASONS[p.kind] ?? p.kind} — \`${offendingSpan(p.span)}\``,
356+
);
357+
return (
358+
`post-stamped: REFUSED — ${rows.length} double-brace opener(s) in this body are not tokens this tool\n` +
359+
' can render. Nothing was written.\n' +
360+
`${rows.join('\n')}\n\n` +
361+
' Posting them would put the literal text on the card AND leave the artefact unstamped, which is\n' +
362+
' the quiet direction: an opener nothing recognises is substituted by nothing and refused by\n' +
363+
` nothing. The tokens this tool knows are \`${STAMP_TOKEN}\` and \`{{WAS:YYYY-MM-DDThh:mmZ}}\`; a\n` +
364+
' mistyped one is a typo, and a typo must never decide whether a stamp was read. (Spans are\n' +
365+
` clipped to ${SPAN_BYTES} bytes with control characters escaped, so a payload that arrived from a\n` +
366+
' shell read gone wrong stays readable.)'
367+
);
368+
}
208369

209370
/** The clock, in the protocol's own spelling. */
210371
export function stampNow(ms = Date.now()) {
@@ -265,7 +426,7 @@ export function stampRefusals(text, nowMs = Date.now()) {
265426
refusals.push({
266427
kind: 'quoted-not-a-stamp',
267428
detail:
268-
`\`{{WAS:${value}}}\` does not declare a stamp. The quoted route renders a reading of ` +
429+
`\`{{WAS:${offendingSpan(value)}}}\` does not declare a stamp. The quoted route renders a reading of ` +
269430
'something else VERBATIM, so its contents must be one `YYYY-MM-DDThh:mmZ` and nothing else — ' +
270431
'it is a declaration, not a free-text escape from the contract.',
271432
});
@@ -353,6 +514,16 @@ export function renderBody(text, nowMs = Date.now()) {
353514
' reader has to judge; supply a body with --file=PATH or on stdin.',
354515
};
355516
}
517+
// ⛔ Ahead of `stampRefusals`, and not folded into it. Its bare-stamp scan
518+
// reads `maskQuotedStamps`, which is built out of the very regex an
519+
// unrecognised opener defeats — so until every opener is a token, what that
520+
// scan calls "a bare stamp in the opening line" may be the inside of a token
521+
// nobody could parse. One opener, one refusal: the shape first, alone.
522+
const openers = unrecognisedOpeners(raw);
523+
if (openers.length > 0) {
524+
return { ok: false, kind: 'unknown-token', openers, error: unrecognisedOpenerText(openers) };
525+
}
526+
356527
const refusals = stampRefusals(raw, nowMs);
357528
if (refusals.length > 0) return { ok: false, kind: 'stamp-contract', refusals, error: refusalText(refusals) };
358529

@@ -365,19 +536,14 @@ export function renderBody(text, nowMs = Date.now()) {
365536
const substituted = body.split(STAMP_TOKEN).length - 1;
366537
body = body.split(STAMP_TOKEN).join(stamp);
367538

368-
const leftover = body.match(globalOf(ANY_TOKEN_RE));
369-
if (leftover) {
370-
return {
371-
ok: false,
372-
kind: 'unknown-token',
373-
error:
374-
`post-stamped: REFUSED — ${leftover.length} token(s) survived substitution: ${leftover.join(', ')}.\n` +
375-
` Posting them would put the literal text on the card AND leave the artefact unstamped, which is\n` +
376-
` the quiet direction. The tokens this tool knows are \`${STAMP_TOKEN}\` and \`{{WAS:…}}\`; a\n` +
377-
' mistyped one is a typo, and a typo must never decide whether a stamp was read.',
378-
};
379-
}
380-
539+
// ⛔ No second leftover scan here. The one that used to sit at this line
540+
// matched `{{…}}` AFTER substitution, which is both too late and too narrow:
541+
// too late because an opener that never closes is not a leftover of anything,
542+
// and too narrow because its payload class excluded the braces the filed
543+
// artefact's payload carried. `unrecognisedOpeners` above walks every opener
544+
// instead, and the two stamps substituted here carry no braces — so a second
545+
// check at this line could never fire, and a check that cannot fire is a
546+
// check nobody maintains.
381547
return { ok: true, body, stamp, substituted, quoted };
382548
}
383549

@@ -820,14 +986,15 @@ async function main(argv) {
820986
const SELF_TEST_BATTERIES = Object.freeze({
821987
'the token contract: the two spellings, and nothing else': 9,
822988
'the refusals: every route that must not reach the board': 20,
989+
'the opener scan: every `{{` is a token this tool renders, or the body is refused': 35,
823990
'the direction check: a stamp no act can have read': 22,
824991
'the substitution: one clock, read once, written everywhere': 9,
825992
'the read-back: what the transcript can actually prove': 11,
826993
'the CLI: the one decision a typo must never make': 16,
827994
'the unread-knock check: a refresh cannot void what nobody read': 23,
828995
'the shared rule: this tool and H56 cannot come to disagree': 6,
829996
});
830-
const SELF_TEST_BATTERY_FLOOR = 8;
997+
const SELF_TEST_BATTERY_FLOOR = 9;
831998
const UNATTRIBUTED_BATTERY = '(unattributed)';
832999

8331000
let selfTestReachedVerdict = false;
@@ -882,6 +1049,61 @@ export function selfTest() {
8821049
t('…and states that no flag turns the contract off', refusalText(stampRefusals(OPENING)).includes('There is no flag'));
8831050
t('…and that nothing was written', refusalText(stampRefusals(OPENING)).includes('Nothing was written'));
8841051

1052+
// The filed artefact's shape, in kind: a shell read failed and the quoted
1053+
// slot took a multi-line Node dump. Dumps carry braces, and both payload
1054+
// classes in this file are `[^{}]*`, so nothing matched and the opener was
1055+
// copied to the board — neither rendered nor refused.
1056+
battery('the opener scan: every `{{` is a token this tool renders, or the body is refused');
1057+
const CARD_DUMP =
1058+
'Merged at {{WAS:[eval]:1\n' +
1059+
'JSON.parse(process.env.LANDED).mergedAt\n' +
1060+
' ^\n' +
1061+
"SyntaxError: Unexpected token '}' in JSON at position 0}} — read from the merge commit.";
1062+
t('⭐ the filed repro: a quoted slot holding a Node dump is REFUSED, not copied to the board', renderBody(CARD_DUMP, NOW_MS).ok === false);
1063+
t('…and nothing is rendered from it', renderBody(CARD_DUMP, NOW_MS).body === undefined);
1064+
t('⛔ WHY it used to pass: neither payload class can cross a brace, so nothing matched at all', QUOTED_TOKEN_RE.test(CARD_DUMP) === false && ANY_TOKEN_RE.test(CARD_DUMP) === false);
1065+
t('…so the scan walks openers positionally and names the brace', unrecognisedOpeners(CARD_DUMP)[0].kind === 'brace-in-payload');
1066+
t('…and the refusal prints the span with its newlines ESCAPED', renderBody(CARD_DUMP, NOW_MS).error.split('\n')[2].includes('[eval]:1\\n'));
1067+
t('⛔ …so the dump never reaches the refusal text raw, at any length', renderBody(CARD_DUMP, NOW_MS).error.includes('\nJSON.parse(process.env') === false);
1068+
1069+
const MULTI_LINE_PAYLOAD = 'Merged at {{WAS:[eval]:1\nSyntaxError: Unexpected end of JSON input}} — read from the log.';
1070+
t('a quoted payload spanning LINES is refused', renderBody(MULTI_LINE_PAYLOAD, NOW_MS).ok === false);
1071+
t('…by the shape rule, which owns what a quoted payload may say', kinds(MULTI_LINE_PAYLOAD, NOW_MS).join() === 'quoted-not-a-stamp');
1072+
t('…and its span is escaped and clipped too — one spelling of "show me the offender"', stampRefusals(MULTI_LINE_PAYLOAD, NOW_MS)[0].detail.includes('[eval]:1\\nSyntaxError'));
1073+
1074+
t('an unknown token NAME is refused', renderBody('Claim: {{THEN}} — dispatched.', NOW_MS).ok === false);
1075+
t('…named as a well-formed token this tool does not know', unrecognisedOpeners('{{THEN}}')[0].kind === 'unknown-token-name');
1076+
t('…and the recorded `{{now}}` typo is that same kind', unrecognisedOpeners('Claim: {{now}}')[0].kind === 'unknown-token-name');
1077+
1078+
const UNCLOSED = 'Landing provenance\n\nMerged at {{WAS:2026-09-08T14:00Z — read from the merge commit.';
1079+
t('an opener with NO closer is refused', renderBody(UNCLOSED, NOW_MS).ok === false);
1080+
t('…named as exactly that, rather than guessed at', unrecognisedOpeners(UNCLOSED)[0].kind === 'unclosed-opener');
1081+
t('…and the act-clock token is not exempt: an unclosed `{{NOW` is refused too', unrecognisedOpeners('Claim {{NOW — dispatched.')[0].kind === 'unclosed-opener');
1082+
const UNCLOSED_OPENING = 'Claim: skills seat, {{WAS:2026-09-08T14:00Z — dispatched.';
1083+
t('⭐ ONE opener, ONE refusal: an unclosed opener is reported as the opener it is', renderBody(UNCLOSED_OPENING, NOW_MS).kind === 'unknown-token');
1084+
t('⛔ …and NOT as the positional refusal the unmasked payload would otherwise raise', kinds(UNCLOSED_OPENING, NOW_MS).includes('positional') && renderBody(UNCLOSED_OPENING, NOW_MS).error.includes('positional') === false);
1085+
t('a DOUBLED opener is refused', unrecognisedOpeners('Claim {{{{NOW}}}} — dispatched.')[0].kind === 'nested-opener');
1086+
t('…and a NESTED one, a quoted slot wrapped round the act-clock token', unrecognisedOpeners('Board read {{WAS:{{NOW}}}}.')[0].kind === 'nested-opener');
1087+
t('every opener is walked, not only the first', unrecognisedOpeners('Claim {{now}} and board read {{WAS:{}}}.').length === 2);
1088+
1089+
const SCAN_CONTROL = 'Verdict {{NOW}} — on the board read {{WAS:2026-09-08T14:00Z}}.';
1090+
t('⭐ THE CONTROL: one valid `{{NOW}}` and one valid quoted stamp still render', renderBody(SCAN_CONTROL, NOW_MS).ok === true);
1091+
t('…with the scan finding nothing to refuse', unrecognisedOpeners(SCAN_CONTROL).length === 0);
1092+
t('…and the rendered body carrying no opener at all', renderBody(SCAN_CONTROL, NOW_MS).body.includes('{{') === false);
1093+
t('⛔ NO accepted form narrowed: whitespace inside the declaration still clears the scan', unrecognisedOpeners('read {{WAS: 2026-09-08T14:00Z }}').length === 0 && renderBody('read {{WAS: 2026-09-08T14:00Z }}', NOW_MS).ok === true);
1094+
t('⛔ …and the seconds grain still clears it', unrecognisedOpeners('read {{WAS:2026-09-08T14:00:30Z}}').length === 0);
1095+
t('⛔ …and a bare stamp in prose is no opener\'s business', unrecognisedOpeners('The 2026-09-08T14:00Z ruling stands.').length === 0);
1096+
t('⛔ the scan opens NO escape hatch: the entity spelling is not an opener, so it is prose', unrecognisedOpeners('the token &#123;&#123;NOW&#125;&#125;').length === 0);
1097+
t('⛔ …and a token inside backticks is STILL substituted — a fence is not an escape', renderBody('Write `{{NOW}}` there.', NOW_MS).body === 'Write `2026-09-10T06:37Z` there.');
1098+
1099+
t('the span renderer escapes a newline', offendingSpan('a\nb') === 'a\\nb');
1100+
t('…a carriage return and a tab too', offendingSpan('a\r\tb') === 'a\\r\\tb');
1101+
t('…and any other control byte as an `\\xNN` escape, never as the byte itself', offendingSpan('a\u0007b') === 'a\\x07b');
1102+
t('a span inside the budget is printed whole, with no ellipsis', offendingSpan('{{THEN}}') === '{{THEN}}');
1103+
t(`a longer one is clipped to ${SPAN_BYTES} bytes and says so`, offendingSpan('x'.repeat(100)) === `${'x'.repeat(SPAN_BYTES)}…`);
1104+
t('⛔ …and never cuts a multi-byte character in half', offendingSpan(`${'x'.repeat(SPAN_BYTES - 1)}€€`) === `${'x'.repeat(SPAN_BYTES - 1)}…`);
1105+
t('the budget is counted in BYTES, which is the unit a dump arrives in', SPAN_BYTES === 60 && Buffer.byteLength(offendingSpan('€'.repeat(40)), 'utf8') <= SPAN_BYTES + 3);
1106+
8851107
// The clock this act holds is 06:37:48 — so 06:37Z is the minute it is IN,
8861108
// 06:38Z the first minute it has not reached, and 06:51Z sits 14 minutes
8871109
// ahead, inside H56's drift tolerance and still not a thing anyone read.

0 commit comments

Comments
 (0)