Skip to content

docs(pm-dispatch): widen the stored-body exclamation-deletion clause to the measured bracket trigger - #13088

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-13071-bang-bracket-clause
Aug 29, 2026
Merged

docs(pm-dispatch): widen the stored-body exclamation-deletion clause to the measured bracket trigger#13088
os-litant merged 1 commit into
mainfrom
claude/issue-13071-bang-bracket-clause

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#13071

The 写侧实测行为 · issue body bullet in .claude/skills/pm-dispatch/references/platform-readings.md
recorded the exclamation-mark deletion with a less-than precondition, naming the sequence as the
markup-declaration open tag. An author reading it concluded that text with no less-than in it was not
exposed.

Measured 2026-08-29 on a PR body: the less-than is not required. The trigger is an exclamation mark
immediately followed by a left bracket — the TypeScript non-null assertion before an index, an ordinary
identifier in front of it, and no less-than anywhere in the span. Two independent read channels agreed the
character is gone from the STORED body (MCP read-back, and the rendered page fetched with curl), while the
files on disk were unchanged: write-side storage loss, not a read artifact. All four occurrences lost the
character — two inside a triple-backtick fence, two in inline code spans — so neither carrier protects it.

This is a correction to an existing clause, not a new section. The bullet is rewritten in place at
net-0 lines: the widened trigger strictly subsumes the less-than-prefixed sequence the clause used to
name, and the author-side remedy (spell the operator out in words, or use a placeholder token defined once)
is added beside the existing ones.

Discipline note, since this clause is about its own hazard: the sequence is described in words
throughout — in the file and in this body — and is never written as a literal adjacency. That is also why
this PR carries no reproduction sample.

Before / after

Seven lines out, seven lines in — the whole bullet, .claude/skills/pm-dispatch/references/platform-readings.md
lines 247-253.

Before (741 bytes over 7 lines):

247 | 115B | - **写侧实测行为 · issue body(落库删字节,网页同显)**:sanitizer 按 **tag 形状**删、不按尖括
248 | 120B | 号 —— 行内反引号里的 tag 形状 token(读作未知 HTML 标签者:注释标记、占位符、泛型)整个
249 | 115B | 被删,HTML 注释形状标记裸写被整删留空行;孤立 less-than / greater-than 在行内代码**存活**,
250 | 120B | 非 tag 形状的带尖括号正则在围栏中亦存活。⛔ **围栏不防护 tag 形状 token**:入围栏照删、
251 | 118B | 留空围栏(2026-08-18/20 issue body 四写实测)。**另一坑另计**:「less-than + 感叹号 + 左方括号」
252 | 115B | 序列(markup-declaration 开标记)里的感叹号在存储层被删,幸存文本仍像代码但意义已变;裸
253 | 38B | 「less-than + 感叹号」存活。

After (829 bytes over 7 lines):

247 | 118B | - **写侧实测行为 · issue body(落库删字节,网页同显)**:sanitizer 按 **tag 形状**删、不按尖括号
248 | 119B | —— 行内反引号里的 tag 形状 token(未知标签形:注释标记、占位符、泛型)整个被删,HTML 注
249 | 120B | 释形状标记裸写被整删留空行;孤立 less-than / greater-than(行内)与非 tag 形状带尖括号正则(围
250 | 120B | 栏)**存活**。⛔ **围栏不防护**:照删、留空围栏(2026-08-18/20 四写实测)。**另一坑**:**感叹号
251 | 119B | 紧跟左方括号**即触发(TS 非空断言下标),**无需 less-than**(2026-08-29 PR 正文四处实测,MCP 与渲
252 | 119B | 染页双读一致、盘上未变 ⇒ 落库丢字符;围栏/行内代码四处全丢),幸存文本仍像代码但意
253 | 114B | 义已变;感叹号不接左方括号则存活。作者侧:运算符**用词拼出**,或占位词定义一次。

Bullet bytes 741 to 829 (+88); file bytes 33279 to 33367 (+88); lines 7 to 7. The line breaks are the
canonical greedy wrap produced by the ratchet's own wrapLine export, so every break is one the gate
itself would offer — no break lands after an ASCII comma/semicolon/colon that follows a Han character.

Ratchet

FileMetricCeiling / pinBeforeAfterHeadroom
.claude/.../references/platform-readings.mdlines3143143140
.claude/.../references/platform-readings.mdwidest table row (bytes)0000
.claude/.../references/platform-readings.mdwidest line (bytes)1201201200

Zero-headroom in, zero-headroom out. No re-pin, and no re-wrap of any paragraph outside the edited bullet.

Cut ledger

Everything trimmed to fund the widened clause, with the home each fact survives in. All of them stay inside
the same bullet.

CutSurviving home
读作未知 HTML 标签者 to 未知标签形Same clause: the mechanism (these tokens read as an unknown HTML tag) is kept in compressed form.
issue body inside the 2026-08-18/20 … 四写实测 provenanceThe bullet's own title, 写侧实测行为 · issue body, which already scopes every reading in it.
入围栏 in 入围栏照删Same sentence: its subject is 围栏不防护 and its other half is 留空围栏, so the carrier is still named twice.
tag 形状 token qualifier on ⛔ 围栏不防护Deliberately widened, not merely dropped: the new clause measures the exclamation case lost inside fences too, so fence non-protection is now a property of the fence, and the tail restates it as 围栏/行内代码四处全丢.
在行内代码 / 在围栏中亦 phrasing on the two survival casesSame sentence, as parenthetical carriers (行内) and (围栏) — the carrier qualification is preserved, not generalised.
序列(markup-declaration 开标记) framing, and the 「less-than + 感叹号 + 左方括号」 spellingSuperseded, not cut. The measured trigger (exclamation mark immediately before a left bracket, less-than or not) strictly subsumes the less-than-prefixed sequence, so keeping the narrower spelling would restate the very precondition this card disproves.
裸「less-than + 感叹号」存活Restated as 感叹号不接左方括号则存活, which covers the bare less-than-plus-exclamation case and states the real boundary: what survives is an exclamation mark with no bracket after it.
在存储层被删落库丢字符 in the tail, alongside the on-disk-unchanged evidence that makes it a write-side loss.

Gates

Derived, not recalled: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack at
commit db39dfc1c, change set 1 path(s) — re-derived after the commit and unchanged
(committed 1, working tree 0, untracked 0). All runs below are at 68cb59e0e, working tree clean,
exit codes captured by redirect-then-capture (never through a pipe).

GateExitVerdict line (the gate's own)
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md is 314 lines (ceiling 314; headroom 0). and ✓ … : widest table row is 0 bytes (pin 0; headroom 0).; ✓ check-skill-line-ratchet self-test: 111 cases pass.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 398 file(s) · 4558 bare -- token(s) · 1223 launcher-rooted run(s) · 9 separator(s) JUDGED · 5 vitest-backed script name(s) derived from 80 manifest(s)
pnpm check:doc-authoring0✓ doc authoring guard: 392 files clean — no bare metadata literals. and ✓ doc authoring guard: 48 published skill files clean — no internal issue-id references.
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 206 assertions (…) · live: the real generator declared 9 output(s) and certified this tree
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 425 files / 1453 TS blocks judged clean by @objectstack/formula.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 7281 text file(s) -- 7281 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
node scripts/pm/check-governed-queue-guard.mjs1NOT MEASURED, not red.⛔ Governed Surface Queue Guard: could not read GITHUB_EVENT_PATH (ENOENT …) — the guard reads the workflow event payload and nothing else, so it can only run inside its governed-surface-guard.yml job. Nothing was measured locally; CI runs it for real.

check:doc-formula-expressions first exited 1 with PREREQUISITE NOT MET — the workspace package @objectstack/formula is not built, then again with the same for @objectstack/lint. Both are
"nothing was measured", not findings. Built both through the shared verify lock
(bash scripts/pm/os-verify-lock.sh -c 'pnpm exec turbo run build --filter=… --concurrency=2',
VERDICT command-exit 0) and re-ran to the exit 0 above.

Changeset

None, deliberately. The diff is one file under .claude/, a closed list that publishes nothing, so
skip-changeset applies and is requested at PR open.

Governed surface

The diff touches .claude/**, so this PR is a governed surface under Prime Directive #14: opened as a
draft, no ready flip, no reviewers, no auto-merge, no merge queue. Landing is the maintainer's, by hand.

Generated by Claude Code


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review August 29, 2026 06:58
@os-litant
os-litant added this pull request to the merge queueAug 29, 2026
Merged via the queue into main with commit 47fd377Aug 29, 2026
32 checks passed
@os-litant
os-litant deleted the claude/issue-13071-bang-bracket-clause branch August 29, 2026 09:35
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants

@os-litant@os-zhuang@claude