diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e46a523 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,45 @@ +# Force textual diffs for source and docs. +# +# Why: git classifies a whole file as binary if a NUL byte (0x00) appears in the +# first 8000 bytes. `git diff` then degrades to "Bin 9679 -> 10779 bytes" and +# `git blame` stops working entirely. That happened to server/usage-ledger.js +# (#27): a composite-key separator was written as a raw 0x00 instead of the +# `\u0000` escape, and it survived review precisely because the file could not +# be diffed. Nobody was careless — a single pipeline that eats backslash escapes +# is enough to produce it, and the damage hides itself. +# +# The `diff` attribute tells git to treat these paths as text even when they +# contain bytes that never occur in text files, so the next occurrence shows up +# as a normal +/- diff instead of silently going invisible. It changes nothing +# on disk or in the object store — it only affects how git renders changes. + +# Normalize line endings to LF in the repo (the tree is already 100% LF). +* text=auto + +# Always diff these as text, NUL or not. +*.js diff +*.jsx diff +*.mjs diff +*.cjs diff +*.json diff +*.css diff +*.html diff +*.md diff +*.sh diff +*.yml diff +*.yaml diff +*.sql diff +.env.example diff +Dockerfile diff + +# Genuinely binary — never try to normalize or diff these as text. +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.webp binary +*.pdf binary +*.woff binary +*.woff2 binary +*.ttf binary diff --git a/docs/memory.md b/docs/memory.md index f1c396c..4630c30 100644 --- a/docs/memory.md +++ b/docs/memory.md @@ -291,6 +291,7 @@ kill %1 1. **静默错配比崩溃危险**:引用不存在的 CSS token(ErrorCard 白底白字)、不存在的 class(`className="input"` 原生控件)、错误的函数契约(`llm.embed` 永远返回 null)——三者都不报错,只是安静地渲染成错的样子或永远返回空。**"看起来像空状态"要当成 bug 线索查。** 2. **只在新库上测 = 测不到生产**:session 索引写进基础 schema,全新库没问题,已有库启动即死。563 个测试全绿也拦不住。**改 schema 必须在有数据的库上启动一次。** 3. **列可空 = 隐形数据丢失**:`workspace_id` 一直 nullable,任何忘记带它的 INSERT 都静默成功、然后从所有 scoped 读里消失。#11 用条件 NOT NULL 做了结构性根治。 +4. **源码里的裸控制字节 = 文件从 review 里消失**:`usage-ledger.js` 的复合键分隔符是直接写进源码的裸 `0x00`,而不是 `\u0000` 转义。NUL 一旦落在文件前 8000 字节内,git 就把**整个文件**判成二进制 —— `git diff` 只剩 `Bin N -> M bytes`,`git blame` 彻底失效。**它不需要谁疏忽:任何一个会吞反斜杠转义的管线都能产生它,而且产生之后会把自己藏起来。** #27 修了这个实例,`.gitattributes` 的 `diff` 属性做了结构性兜底(对 NUL 文件也强制文本 diff)。**在全量 diff 里看到源码文件显示 `Bin`,立刻当 bug 查。** ## 7. 与协作者的协议