Conversation
|
Warning Review limit reachedNext included review available in 12 minutes. View limit detailsLimit details: You’ve used the included review currently available. Your 97 included PR review attempts over the past 7 days set your current allowance at 1 review per hour. Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: 📒 Files selected for processing (2)
Comment |
|
@coderabbitai review |
|
lemone112
left a comment
There was a problem hiding this comment.
Автоматизация из ChatGPT от агента GPT-5.6 Sol
BLOCKER — CORR-001: provenance silently aliases distinct Git paths with non-UTF-8 bytes.
GitHub не позволил оформить это как REQUEST_CHANGES: активное подключение действует от того же пользователя, который является автором PR, и API вернул 422 Review Can not request changes on your own pull request. Поэтому этот COMMENT содержит доказанный blocker, но технический merge-block этим review не установлен.
Инвариант
PR заявляет: если tracked-байты рабочего дерева отличаются от объявленного Git revision, изменение должно быть обнаружено даже когда git status скрывает его через assume-unchanged / skip-worktree.
COUNTEREXAMPLE FOUND
На exact head 5d1179d342f58bf4956b824e1ea76023323b2891 worktreeFingerprint() и revisionFingerprint() получают NUL-delimited Git output как Buffer, но затем делают raw.toString('utf8').split('\0'). На POSIX Git имя файла — последовательность байтов, не обязательный UTF-8. Два разных пути поэтому могут схлопнуться в одну JS-строку через U+FFFD.
Реальный воспроизводимый witness (Git 2.47.3, Node 22.16.0, POSIX):
- В одном repo закоммитить два обычных файла с одинаковым содержимым
safe\n:- raw path bytes
bad-\xff.js; - UTF-8 path
bad-�.js(байтыEF BF BD).
- raw path bytes
- Для
bad-\xff.jsпоставитьassume-unchangedчерез NUL-delimitedgit update-index -z --stdin. git status --porcelain= пусто.- До мутации текущая логика даёт:
revisionFingerprint(..., {verifyWorkingTree:true}) = c521cf8a58712b3be77998825ffc0eccf852170e686c245f9c92730f35851deeworktreeFingerprint = c521cf8a58712b3be77998825ffc0eccf852170e686c245f9c92730f35851dee
- Изменить только raw
bad-\xff.jsнаEVIL\n. - После мутации
git statusвсё ещё пуст, оба fingerprint остаются теми же, хотя скрытый tracked-файл содержитEVIL\n, аbad-�.jsостаётсяsafe\n.
Причина непосредственно следует из exact-head source: оба raw path превращаются в bad-�.js; последующий path.join/readFileSync дважды читает UTF-8-файл и вообще не читает изменённый raw path. worktreeSha256 имеет тот же lossy decode, поэтому post-build/post-run guard также не замечает эту мутацию.
Почему это blocker
Это не косметический unsupported edge: текущий код не fail-closed на неподдерживаемом имени, а выдаёт доказательство clean revision при реально отличающихся tracked bytes — ровно ложное утверждение, которое этот PR должен устранить. В non-goals перечислены symlink/submodule/arbitrary transforms, но не non-UTF-8 обычные tracked-файлы. Даже если их не поддерживать, корректная семантика — явный reject, не alias/pass.
Минимальное исправление
Не нужно поддерживать произвольные byte-paths end-to-end. Проще ввести один parser NUL-delimited Git paths, который перед преобразованием в JS string требует canonical UTF-8 round-trip:
decoded = rawName.toString('utf8') и Buffer.from(decoded, 'utf8').equals(rawName), иначе fail closed (provenance: tracked path не является canonical UTF-8).
Один и тот же закон нужен минимум в revisionFingerprint (ls-tree) и worktreeFingerprint (ls-files). В ls-tree metadata до TAB можно разбирать как ASCII, bytes после TAB — отдельно. Добавить regression: одновременно bad-\xff.js + bad-�.js, hidden mutation первого, ожидание reject до build.
Autofix не применён: доступный write-интерфейс безопасно заменяет только целый UTF-8 файл; точечного patch-примитива нет. Перезаписывать весь provenance.mjs ради локального fix увеличило бы blast radius. Это ограничение инструмента, не неоднозначность исправления.
Независимая проверка / falsifier
Finding опровергается, если текущий exact-head код либо сохраняет raw path identity без lossy UTF-8 decode, либо отклоняет non-canonical UTF-8 path до чтения рабочего дерева. На 5d1179d… ни одного нет. Exact source подтверждает lossy decode в обоих fingerprint-путях; отдельный executable witness воспроизводит неизменный hash после реальной hidden mutation.
CodeRabbit arbitration
CodeRabbit на этом exact snapshot положительно сообщил Review rate limited; ручной @coderabbitai review также ответил Action not completed — Review rate limited. Поэтому выполнен replacement audit. Отсутствие CodeRabbit-review не считается PASS.
Evidence ledger
- FACT / CHECK=YES (exact GitHub source): head
5d1179d…содержитraw.toString('utf8').split('\0')вrevisionFingerprintиworktreeFingerprint. - FACT / CHECK=YES (local executable counterexample): реальный Git repo после hidden mutation сохраняет одинаковые revision/worktree fingerprints; изменённый raw-path файл содержит
EVIL\n. - FACT / CHECK=YES (remote): exact-head
CI= SUCCESS; browser/consumer checks зелёные. Они не содержат этот counterexample, поэтому finding не опровергают. - FACT / CHECK=YES: base/merge-base
c613abd7f222889ce345752a35adab80a9259726, head ровно на один commit впереди; diff = provenance helper + tests. - FACT / CHECK=YES: CodeRabbit rate-limit подтверждён его собственным ответом.
- Exact-head remote запуск нового non-UTF8 counterexample: CHECK=NOT RUN — такого теста в head нет.
- Технический REQUEST_CHANGES: CHECK=NO — GitHub API отверг его, потому что reviewer = автор PR.
Validity envelope: head 5d1179d342f58bf4956b824e1ea76023323b2891; base/merge-base c613abd7f222889ce345752a35adab80a9259726; CodeRabbit takeover = active due explicit rate-limit; proof scope = POSIX Git path-byte semantics + текущий provenance algorithm.
Дополнительно: PR нацелен в stacked base fix/independent-motion-conformance-20260905, а видимые org/repo rulesets применяют merge enforcement к ~DEFAULT_BRANCH. Поэтому и помимо ограничения self-review здесь нет доказанного ruleset-level запрета merge на этой промежуточной ветке.
|
Закрываю как superseded, не как «ненужный»: capability остаётся актуальной по Replacement: #358. Перед переносом проверены оба base blob затрагиваемых файлов: родитель semantic commit этого PR и current |
Пользовательский результат
Проверка входов benchmark отклоняет изменённые tracked-байты, даже когда
git statusскрывает их из-заassume-unchangedилиskip-worktree.Механически выделены ровно два файла из
64a0b094d73aa898b19bf8972c5356ee7644c9c8, без изменения их содержимого. База — #300,c613abd7f222889ce345752a35adab80a9259726. Transform-эксперимент остаётся в #302.Контракт
trackedRevisionSha256; байты сверяются с объявленным коммитом до сборки и при последующей проверке неизменности.cat-file --batch; заголовки и границы содержимого проверяются.Доказательство
Проверены скрытые изменения до сборки и после неё, LF/CRLF, бинарные отличия, custom filters, replacement refs, несколько пакетов объектов и некорректные заголовки. Численное ядро и DOM/WAAPI/layout не изменены; численный property/fuzz-оракул и браузерный тест для этого diff не требуются. POSIX-тест имён с кавычками, обратной косой чертой и переводом строки штатно пропущен на Windows; он выполнен в зелёном удалённом Linux CI.
Идентичные blob OID:
bench/compare/provenance.mjs:11b6e7c2eaf1c405bbf77a759271747535c2edf9test/benchmark-provenance.test.ts:c30a8e662a57f1d14a52bccd5aaf1f78dc016c6eАрхитектура
Cleanup/cancel/destroy и stale-frame вне этого diff. Общий helper provenance сохраняет единственного владельца Git-доказательства.
Производительность
Производительность публичного движка не затрагивается. Ускорение, глобальная герметичность, воспроизводимость всей сборки и допуск performance-результатов не заявляются.
Риски и не-цели
Область проверки конечна: Git с 40-символьными OID, обычные файлы, поддерживаемая нормализация текста. Символические ссылки, подмодули и произвольные преобразования не входят в проверяемую поверхность чистого checkout. Независимые protocol/provenance review исходных blob и отдельная проверка идентичности выделения завершены: PASS. Merge, выпуск и deploy не выполняются.
Документация и выпуск
Документация, exports и
CHANGELOG.mdне изменены: срез относится к внутреннему доказательству входов benchmark, а не к API пакета. Статус проверок остаётся в PR.Гейты
pnpm install --frozen-lockfilepnpm check:static— включаетpnpm typecheckpnpm buildpnpm test --maxWorkers 4— 268 файлов прошли, 1 пропущен; 4087 тестов прошли, 22 пропущеныgit diff --checkpnpm size— локально не запускалсяpnpm pack:smoke— локально не запускалсяpnpm mutation— численное ядро не измененоПервый полный запуск: 4086 прошли, один shell syntax-тест превысил лимит при запуске Windows/WSL
bash. После выбора установленного Git Bash через PATH только дочернего процесса полный запуск прошёл; код и общая конфигурация не менялись.Связано с #300, #302.
Удалённые exact-head проверки на 5d1179d: CI и browser — SUCCESS. CI включает size и pack smoke. Git fixture POSIX-пути проверены Linux-набором. Откат после возможного merge в main — revert этого PR; исходники runtime не затронуты.