From 22e6ffedc31901830c35f04c1198b8cf16b58b54 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 16:15:22 +0000 Subject: [PATCH 1/2] docs(agents): sanitizer clause states the two measured body-mutation shapes; Skills section stops enumerating; platform-readings carries the read-layer facts AGENTS.md gains the binding sanitizer clause naming the measured shapes (storage-side exclamation-mark deletion from the markup-declaration opener; API-side truncation at script-tag-shaped tokens) with the spell-it-out-in-words author rule, and its Skills section replaces both hand-written inventories with the two root paths (the filesystem is the catalog). platform-readings.md carries the same facts as fact rows within the 134-line ratchet ceiling. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01WswfK2yNYT9hNnMH6TzAwL --- .../references/platform-readings.md | 6 +-- AGENTS.md | 44 ++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/.claude/skills/pm-dispatch/references/platform-readings.md b/.claude/skills/pm-dispatch/references/platform-readings.md index 2a7b6f53ad..aa4e40e76c 100644 --- a/.claude/skills/pm-dispatch/references/platform-readings.md +++ b/.claude/skills/pm-dispatch/references/platform-readings.md @@ -101,9 +101,9 @@ 静默死 ≠ 测试通过;并发输出的「相邻」≠「因果」(先查 `turbo.json` 依赖边),⛔ 不 只看 tail;公开发出的诊断被推翻时,更正发在同样公开的位置,据它开的 PR 撤回 draft、解绑 `Fixes`。 - **判「正文被截断」必须双读取**:`.body` 原文 + `Accept: - application/vnd.github.full+json` 的 `.body_html`,两者同一处断掉才算 issue 端截 - 断,单一读法的尾部缺失先算读取端截断(工具输出上限、分页、切片)。写侧另一半: - sanitizer 会在**写入时就地删除**短 `<…>` 片段(HTML 注释标记、`` 类占位符、泛 + application/vnd.github.full+json` 的 `.body_html`,两者同一处断掉才算 issue 端截断。读侧实测有确定性触发:正文含字面 script 开标记形状的 token(less-than 紧跟 script 字样;doctype 开标记、object 标签形状同触发)时,API/MCP 读回在该 token 处静默截断而网页全文完好 —— 存储体无损,⛔ 不「修复」只在 API 读短的卡:先 WebFetch 渲染页核对全文,重写会毁掉本来正确的正文。 +- **落库删字节,网页同显、围栏不防护**:「less-than + 感叹号 + 左方括号」序列(markup-declaration 开标记,恰是负向后行断言接字符类的形状)里的感叹号在存储层被删,幸存文本仍像代码但意义已变;裸「less-than + 感叹号」存活。作者规则:正则字面量与 script 形状 token 要么进围栏且把危险字符用词拼出,要么整句用词描述 —— 必须字面携带这类形状的正文托付不了 GitHub。 +- 写侧另一半:sanitizer 会在**写入时就地删除**短 `<…>` 片段(HTML 注释标记、`` 类占位符、泛 型),反引号与围栏**不提供保护** —— 要保留字面尖括号一律写 HTML 实体 `<` / `>`,要存活的注释类标记改写成可见 markdown;含这类片段的正文,写后回读逐个确认仍在(失效完全静默)。 - **并行 spec PR 同动 pin 计数断言**(被踢不是事故,按 os-regen 序再解一轮):解冲 突两侧收据都保留、按合并顺序堆叠,新计数**从合并后源码重数**(操作数是文件本身不 diff --git a/AGENTS.md b/AGENTS.md index 1940dfde10..a809c1309b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -300,6 +300,38 @@ every `update_pull_request` edit; the session-URL form survives both write paths this is unknown, and the guidance does not depend on the answer — do not spend a session establishing it. Comments are a different path and unaffected. +**The platform also mutates body BYTES — two measured shapes; spell the poison +tokens out in words, never write them literally.** (This clause obeys its own rule: +a clause that cannot survive its own channel is self-defeating.) Both shapes are +silent, ignore backticks and code fences, and leave text that still reads as +intended prose or code: + +1. **Storage-side deletion** — the exclamation mark is deleted from the + markup-declaration opener: the byte sequence less-than, exclamation mark, open + square bracket, which is exactly the shape of a regex negative lookbehind before + a character class. Measured by two independent authors on the same construct; + the rendered web page shows the same loss, so the damage is at rest. The + surviving text still looks like code and no longer means what the author wrote + (a correct regex proposal read back as an apparent syntax error). A bare + less-than + exclamation mark without the bracket survives. +2. **API-side truncation** — reading a body through the GitHub API/MCP tools cuts + it off at a literal script-tag-shaped token (a doctype opener and an + object-tag-shaped token also trigger it). Everything after vanishes with no + error or marker, while the web page carries the full text — the damage is in + the read path, not storage. ⛔ Never "repair" a card that reads short only + through the API: fetch the rendered page first; the stored body is probably + intact, and a rewrite destroys a correct card. + +The operative rule for authors: regex literals and script-tag-shaped tokens go in +fenced code **with the dangerous character spelled out in words**, or are described +entirely in words — fences do NOT protect them, and a load-bearing literal that +cannot survive its own channel must not be entrusted to a GitHub body at all. After +writing a body that must carry any less-than fragment, read it back and verify the +fragment survived (write the HTML entity form when it must render literally). The +older guidance — a less-than sign followed by a letter is stripped as an HTML tag — +is one member of this family, not its boundary: probes measured that form +*surviving* inside code fences while the two shapes above were destroyed there. + Even inside your own worktree, operate defensively: 1. **Only touch the files your task needs.** Don't "fix" unrelated diffs, reverts, or @@ -646,12 +678,14 @@ their output is current; the wrapper reports that each run rather than staying s ## Skills (`skills/`) -Consult the matching `SKILL.md` when working in its domain: `objectstack-platform`, `objectstack-data`, `objectstack-query`, `objectstack-api`, `objectstack-ui`, `objectstack-automation`, `objectstack-ai`, `objectstack-i18n`, `objectstack-formula` (CEL). +Two roots; **the filesystem is the catalog**. Consult the matching `SKILL.md` when +working in its domain — browse the directory, never a hand-written list here (two +such lists drifted stale as skills landed; a reader who trusts a list cannot see +what it is missing): -`skills/` is the **published** catalog (it ships to customer projects). Repo-internal -agent playbooks live in `.claude/skills/` and must carry `metadata.internal: true`: -`dogfood-verification` (boot and drive the real app in a browser) and -`spec-property-retirement` (ADR-0049 enforce-or-remove — the full retirement kit). +- `skills/` — the **published** catalog (it ships to customer projects). +- `.claude/skills/` — repo-internal agent playbooks; every entry must carry + `metadata.internal: true`. ⛔ **Both roots are governed surfaces**: a PR touching either is human-merge only and may never be queued, armed or flipped out of draft — **Prime Directive #14**. No per-PR check From 1334c1cc3b8db1494327780dd7dab3462791a5c1 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 23:54:46 +0000 Subject: [PATCH 2/2] =?UTF-8?q?docs(agents):=20compress=20the=20body-mutat?= =?UTF-8?q?ion=20clause=20to=20six=20operative=20lines=20(maintainer=20siz?= =?UTF-8?q?e=20review)=20=E2=80=94=20facts=20stay=20in=20platform-readings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01WswfK2yNYT9hNnMH6TzAwL --- AGENTS.md | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a809c1309b..1b67449644 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -300,37 +300,12 @@ every `update_pull_request` edit; the session-URL form survives both write paths this is unknown, and the guidance does not depend on the answer — do not spend a session establishing it. Comments are a different path and unaffected. -**The platform also mutates body BYTES — two measured shapes; spell the poison -tokens out in words, never write them literally.** (This clause obeys its own rule: -a clause that cannot survive its own channel is self-defeating.) Both shapes are -silent, ignore backticks and code fences, and leave text that still reads as -intended prose or code: - -1. **Storage-side deletion** — the exclamation mark is deleted from the - markup-declaration opener: the byte sequence less-than, exclamation mark, open - square bracket, which is exactly the shape of a regex negative lookbehind before - a character class. Measured by two independent authors on the same construct; - the rendered web page shows the same loss, so the damage is at rest. The - surviving text still looks like code and no longer means what the author wrote - (a correct regex proposal read back as an apparent syntax error). A bare - less-than + exclamation mark without the bracket survives. -2. **API-side truncation** — reading a body through the GitHub API/MCP tools cuts - it off at a literal script-tag-shaped token (a doctype opener and an - object-tag-shaped token also trigger it). Everything after vanishes with no - error or marker, while the web page carries the full text — the damage is in - the read path, not storage. ⛔ Never "repair" a card that reads short only - through the API: fetch the rendered page first; the stored body is probably - intact, and a rewrite destroys a correct card. - -The operative rule for authors: regex literals and script-tag-shaped tokens go in -fenced code **with the dangerous character spelled out in words**, or are described -entirely in words — fences do NOT protect them, and a load-bearing literal that -cannot survive its own channel must not be entrusted to a GitHub body at all. After -writing a body that must carry any less-than fragment, read it back and verify the -fragment survived (write the HTML entity form when it must render literally). The -older guidance — a less-than sign followed by a letter is stripped as an HTML tag — -is one member of this family, not its boundary: probes measured that form -*surviving* inside code fences while the two shapes above were destroyed there. +**GitHub mutates body BYTES — spell poison-shaped tokens out in words, never literally.** +Regex literals and script-tag-shaped tokens go in fenced code with the dangerous +character spelled out, or are described in words (fences do NOT protect them); after +writing any less-than fragment, read the body back and verify it survived. The two +measured mutation shapes and their triggers live in pm-dispatch `references/platform-readings.md`. +⛔ A body reading short only through the API is probably intact — check the rendered page before "repairing" it; a rewrite destroys a correct card. Even inside your own worktree, operate defensively: