Skip to content

fix(bench): проверять tracked-байты объявленного Git revision - #305

Closed
lemone112 wants to merge 1 commit into
fix/independent-motion-conformance-20260905from
test/git-provenance-contract-20260905
Closed

lemone112 wants to merge 1 commit into
fix/independent-motion-conformance-20260905from
test/git-provenance-contract-20260905

Conversation

@lemone112

@lemone112 lemone112 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Пользовательский результат

Проверка входов benchmark отклоняет изменённые tracked-байты, даже когда git status скрывает их из-за assume-unchanged или skip-worktree.

Механически выделены ровно два файла из 64a0b094d73aa898b19bf8972c5356ee7644c9c8, без изменения их содержимого. База — #300, c613abd7f222889ce345752a35adab80a9259726. Transform-эксперимент остаётся в #302.

Контракт

  • Чистый checkout получает проверяемый trackedRevisionSha256; байты сверяются с объявленным коммитом до сборки и при последующей проверке неизменности.
  • Поддержаны обычные tracked-файлы и допустимое Git-преобразование LF/CRLF. Бинарные изменения, пропуски файлов и произвольные clean-фильтры не принимаются за чистый revision.
  • Replacement refs не подменяют объявленные объекты. Чтение идёт пакетами до 128 объектов через OID-only cat-file --batch; заголовки и границы содержимого проверяются.
  • Git-fixture изолирует global/system config. Это не утверждение о полной герметичности рабочей среды или всех зависимостей сборки.

Доказательство

  • Есть characterization-тест, если меняется существующее поведение
  • RED выполнены в исходном срезе, перенесены побайтно: скрытые изменения, hostile Git config, неправильный batch-протокол и четыре malformed-header контрпримера. При механическом выделении новый RED не требовался и не запускался.
  • Регрессионный тест защищает класс дефекта

Проверены скрытые изменения до сборки и после неё, LF/CRLF, бинарные отличия, custom filters, replacement refs, несколько пакетов объектов и некорректные заголовки. Численное ядро и DOM/WAAPI/layout не изменены; численный property/fuzz-оракул и браузерный тест для этого diff не требуются. POSIX-тест имён с кавычками, обратной косой чертой и переводом строки штатно пропущен на Windows; он выполнен в зелёном удалённом Linux CI.

Идентичные blob OID:

  • bench/compare/provenance.mjs: 11b6e7c2eaf1c405bbf77a759271747535c2edf9
  • test/benchmark-provenance.test.ts: c30a8e662a57f1d14a52bccd5aaf1f78dc016c6e

Архитектура

  • Сохранены границы headless domain → platform adapter → binding
  • Не появился второй источник правды
  • Публичная поверхность и exports обновлены синхронно — изменений нет
  • Неиспользуемые субпути не увеличивают бандл потребителя — runtime не изменён

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-lockfile
  • pnpm check:static — включает pnpm typecheck
  • pnpm build
  • pnpm test --maxWorkers 4 — 268 файлов прошли, 1 пропущен; 4087 тестов прошли, 22 пропущены
  • git diff --check
  • pnpm size — локально не запускался
  • pnpm pack:smoke — локально не запускался
  • pnpm mutation — численное ядро не изменено
  • Независимое review исходных blob на 64a0b09 — PASS; отдельное immutable-object review подтвердило их точную идентичность в 5d1179d.
  • Все восемь исходных CodeRabbit-тредов test(bench): pair public transform lifecycle with semantic guards #302 имеют disposition и разрешены. CodeRabbit нового PR запрошен отдельно и вернул rate-limit; финального ревью этого PR от него нет.

Первый полный запуск: 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 не затронуты.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 12 minutes.

Check out review usage here.

View limit details

Limit 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.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: 5e64380a-723b-4915-b63a-7ee667949c55

📥 Commits

Reviewing files that changed from the base of the PR and between c613abd and 5d1179d.

📒 Files selected for processing (2)
  • bench/compare/provenance.mjs
  • test/benchmark-provenance.test.ts

Comment @coderabbitai help to get the list of available commands.

@lemone112

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@lemone112 lemone112 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Автоматизация из 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):

  1. В одном repo закоммитить два обычных файла с одинаковым содержимым safe\n:
    • raw path bytes bad-\xff.js;
    • UTF-8 path bad-�.js (байты EF BF BD).
  2. Для bad-\xff.js поставить assume-unchanged через NUL-delimited git update-index -z --stdin.
  3. git status --porcelain = пусто.
  4. До мутации текущая логика даёт:
    • revisionFingerprint(..., {verifyWorkingTree:true}) = c521cf8a58712b3be77998825ffc0eccf852170e686c245f9c92730f35851dee
    • worktreeFingerprint = c521cf8a58712b3be77998825ffc0eccf852170e686c245f9c92730f35851dee
  5. Изменить только raw bad-\xff.js на EVIL\n.
  6. После мутации 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 на этой промежуточной ветке.

Copy link
Copy Markdown
Contributor Author

Закрываю как superseded, не как «ненужный»: capability остаётся актуальной по agents-config/main@155a263d3ef2ee18f16dbff05adbb21bd206e63c (plans/lab-motion-production/r10.md), но этот PR сильно разошёлся с current main и тащит старый stacked snapshot.

Replacement: #358.

Перед переносом проверены оба base blob затрагиваемых файлов: родитель semantic commit этого PR и current main@3ec1c94ce4acd18a5b2ed3ac83ad92728bb1e55e имеют идентичные blobs для bench/compare/provenance.mjs (9803b104…) и test/benchmark-provenance.test.ts (e8b0d9a0…). Поэтому #358 переносит ровно живую двухфайловую semantic delta поверх current main, без старых 13 commits и без потери intervening work. #358 остаётся draft до fresh exact-head CI/review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant