Проблема
aggregate/sarif_read.parse_sarif пропускает SARIF-результат, у которого нет ни одного location с непустым artifactLocation.uri, и не считает его нигде. Находка исчезает беззвучно — в ledger'е (coverage) для неё нет ни счётчика, ни причины.
Это ровно то, чего вся остальная нормализация избегает: неотображённое правило попадает в uncategorized и всплывает в uncategorized_rules, третьесторонняя находка попадает в suppressed_by, диагностика анализа — в analysis_skipped_by. Ledger отказывается терять находку молча — кроме этого одного места.
Масштаб — измерен, не оценён
По записанному STS-корпусу (sts_audit/*.sarif):
| tool | результатов в SARIF | с пригодным location | потеряно |
|---|
| own-check | 613 | 613 | 0 |
| codeql | 9 634 | 9 634 | 0 |
| infersharp | 207 | 207 | 0 |
| roslyn | 64 064 | 62 943 | 1 121 |
| итого | 74 518 | 73 397 | 1 121 (1.5 %) |
coverage.total: 73 397 в sts_audit/findings.json — это уже число после потери. То есть отчёт, который в остальном честен до последней находки, на полтора процента корпуса просто не знает, что они были.
Почему это не было исправлено в срезе 1A
1A (#56) переносил нормализатор из устаревшего Own.NET/audit/aggregate/ с обещанием побайтового совпадения payload'а. Исправление здесь меняет coverage — то есть ровно то, что срез обещал не менять, и чем он доказывался. Поэтому поведение было сохранено дословно и закреплено тестом (20 результатов читаются как 19 в parity-фикстуре), чтобы оно не уехало незаметно, а исправление вынесено сюда.
По той же причине это не входит и в 1B: 1B меняет форму записи и идентичность, а не cardinality. Если внезапно вернуть тысячу ранее терявшихся результатов в том же срезе, будет невозможно понять, какая часть разницы вызвана новой схемой, а какая — восстановлением данных.
Что нужно сделать
- Считать такие результаты в
coverage — отдельным счётчиком с разбивкой по инструменту и, где возможно, по правилу. Рабочее имя: no_physical_location / no_physical_location_by. - Решить, что с ними делать дальше, и решение обосновать, а не выбрать по умолчанию:
- оставить вне
findings (как сейчас), но видимыми в ledger'е — минимальный честный вариант; - либо впускать их с
path: "" / line: 0 — но тогда они попадут в pattern_id и в отчёт, и надо понимать, что это за находки. По беглому взгляду это Roslyn-диагностики уровня проекта/сборки, а не файла.
- Разобраться, действительно ли у всех 1 121 нет location, или часть теряется на первом location без
uri при наличии пригодного второго (сейчас _first_location возвращает первый с uri, так что это скорее не так — но это надо проверить, а не предположить). - Обновить
docs/normalization.md: раздел «What is deliberately still missing» описывает этот gap как сохранённый намеренно; после исправления он должен описывать поведение.
Приёмка
- Число, которое ledger сообщает как прочитанное, сходится с числом результатов в исходных SARIF-файлах:
total + no_physical_location == sum(len(run.results)). - Parity-фикстура обновлена осознанно, с явной записью, что изменение payload'а — цель этого изменения, а не побочный эффект.
- Разница на реальном корпусе измерена и записана: сколько результатов вернулось, какого инструмента, каких правил.
Refs PhysShell/Own.NET#266, #56.
Проблема
aggregate/sarif_read.parse_sarifпропускает SARIF-результат, у которого нет ни одного location с непустымartifactLocation.uri, и не считает его нигде. Находка исчезает беззвучно — в ledger'е (coverage) для неё нет ни счётчика, ни причины.Это ровно то, чего вся остальная нормализация избегает: неотображённое правило попадает в
uncategorizedи всплывает вuncategorized_rules, третьесторонняя находка попадает вsuppressed_by, диагностика анализа — вanalysis_skipped_by. Ledger отказывается терять находку молча — кроме этого одного места.Масштаб — измерен, не оценён
По записанному STS-корпусу (
sts_audit/*.sarif):coverage.total: 73 397вsts_audit/findings.json— это уже число после потери. То есть отчёт, который в остальном честен до последней находки, на полтора процента корпуса просто не знает, что они были.Почему это не было исправлено в срезе 1A
1A (#56) переносил нормализатор из устаревшего
Own.NET/audit/aggregate/с обещанием побайтового совпадения payload'а. Исправление здесь меняетcoverage— то есть ровно то, что срез обещал не менять, и чем он доказывался. Поэтому поведение было сохранено дословно и закреплено тестом (20результатов читаются как19в parity-фикстуре), чтобы оно не уехало незаметно, а исправление вынесено сюда.По той же причине это не входит и в 1B: 1B меняет форму записи и идентичность, а не cardinality. Если внезапно вернуть тысячу ранее терявшихся результатов в том же срезе, будет невозможно понять, какая часть разницы вызвана новой схемой, а какая — восстановлением данных.
Что нужно сделать
coverage— отдельным счётчиком с разбивкой по инструменту и, где возможно, по правилу. Рабочее имя:no_physical_location/no_physical_location_by.findings(как сейчас), но видимыми в ledger'е — минимальный честный вариант;path: ""/line: 0— но тогда они попадут вpattern_idи в отчёт, и надо понимать, что это за находки. По беглому взгляду это Roslyn-диагностики уровня проекта/сборки, а не файла.uriпри наличии пригодного второго (сейчас_first_locationвозвращает первый с uri, так что это скорее не так — но это надо проверить, а не предположить).docs/normalization.md: раздел «What is deliberately still missing» описывает этот gap как сохранённый намеренно; после исправления он должен описывать поведение.Приёмка
total + no_physical_location == sum(len(run.results)).Refs PhysShell/Own.NET#266, #56.