scaneval 2.0.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. scaneval-2.0.0a1/.github/workflows/ci.yml +155 -0
  2. scaneval-2.0.0a1/.github/workflows/publish-packages.yml +116 -0
  3. scaneval-2.0.0a1/.gitignore +35 -0
  4. scaneval-2.0.0a1/LICENSE +21 -0
  5. scaneval-2.0.0a1/MANIFEST.in +29 -0
  6. scaneval-2.0.0a1/PKG-INFO +145 -0
  7. scaneval-2.0.0a1/README.md +149 -0
  8. scaneval-2.0.0a1/README_PYPI.md +110 -0
  9. scaneval-2.0.0a1/containers/sv-agent/Dockerfile +155 -0
  10. scaneval-2.0.0a1/containers/sv-agent/Dockerfile.dockerignore +23 -0
  11. scaneval-2.0.0a1/containers/sv-agent/README.md +238 -0
  12. scaneval-2.0.0a1/containers/sv-agent/build.sh +62 -0
  13. scaneval-2.0.0a1/containers/sv-agent/package-lock.json +1537 -0
  14. scaneval-2.0.0a1/containers/sv-agent/package.json +15 -0
  15. scaneval-2.0.0a1/containers/sv-agent/pi-cli.mjs +8 -0
  16. scaneval-2.0.0a1/containers/sv-agent/write-runtime-receipt.mjs +142 -0
  17. scaneval-2.0.0a1/corpus/benchmarks/README.md +32 -0
  18. scaneval-2.0.0a1/corpus/benchmarks/inventory.json +199 -0
  19. scaneval-2.0.0a1/corpus/diverse/README.md +123 -0
  20. scaneval-2.0.0a1/corpus/diverse/machine-review.json +3272 -0
  21. scaneval-2.0.0a1/corpus/diverse/machine-validation.json +102 -0
  22. scaneval-2.0.0a1/corpus/diverse/pack.json +12211 -0
  23. scaneval-2.0.0a1/corpus/diverse/review-history/18-case-selection-review.json +50 -0
  24. scaneval-2.0.0a1/corpus/diverse/selection-rationale.json +396 -0
  25. scaneval-2.0.0a1/corpus/diverse/severity-distribution.json +1830 -0
  26. scaneval-2.0.0a1/corpus/diverse/snapshot-inventory.json +5274 -0
  27. scaneval-2.0.0a1/corpus/diverse/upstream-evidence.json +5278 -0
  28. scaneval-2.0.0a1/docs/AGGREGATION.md +172 -0
  29. scaneval-2.0.0a1/docs/BRING_YOUR_OWN_CORPUS.md +1298 -0
  30. scaneval-2.0.0a1/docs/CLOSED_BOOK.md +121 -0
  31. scaneval-2.0.0a1/docs/CODEX_QUOTA_GUARD.md +254 -0
  32. scaneval-2.0.0a1/docs/COLLECTORS.md +659 -0
  33. scaneval-2.0.0a1/docs/DATASET_ADAPTERS.md +285 -0
  34. scaneval-2.0.0a1/docs/DESIGN_DECISIONS.md +547 -0
  35. scaneval-2.0.0a1/docs/DIAGNOSTICS.md +417 -0
  36. scaneval-2.0.0a1/docs/EVALUATION_MATH.md +332 -0
  37. scaneval-2.0.0a1/docs/EXPERIMENT_MATRIX.md +181 -0
  38. scaneval-2.0.0a1/docs/GATE.md +82 -0
  39. scaneval-2.0.0a1/docs/IDENTITY_REDUCTION.md +180 -0
  40. scaneval-2.0.0a1/docs/INITIAL_BUILD.md +524 -0
  41. scaneval-2.0.0a1/docs/INSPECT_OBSERVABILITY_COMPARISON.md +284 -0
  42. scaneval-2.0.0a1/docs/INVESTIGATION.md +140 -0
  43. scaneval-2.0.0a1/docs/MODEL_CUTOFFS.md +206 -0
  44. scaneval-2.0.0a1/docs/OBSERVER_SDK.md +428 -0
  45. scaneval-2.0.0a1/docs/OPEN_CONTEXT.md +344 -0
  46. scaneval-2.0.0a1/docs/PRECISION.md +132 -0
  47. scaneval-2.0.0a1/docs/RELEASING.md +84 -0
  48. scaneval-2.0.0a1/docs/SARIF_IMPORT.md +229 -0
  49. scaneval-2.0.0a1/docs/SEVERITY.md +115 -0
  50. scaneval-2.0.0a1/docs/THREAT_MODEL.md +426 -0
  51. scaneval-2.0.0a1/docs/designs/chronology-projection.md +78 -0
  52. scaneval-2.0.0a1/docs/designs/codex-quota-guard.md +202 -0
  53. scaneval-2.0.0a1/docs/designs/condition-review-fixes.md +283 -0
  54. scaneval-2.0.0a1/docs/designs/deepsec-curated-processing.md +230 -0
  55. scaneval-2.0.0a1/docs/designs/deepsec-native-kinds.md +35 -0
  56. scaneval-2.0.0a1/docs/designs/model-cutoff-eligibility.md +109 -0
  57. scaneval-2.0.0a1/docs/designs/scanner-adapter-builder.md +25 -0
  58. scaneval-2.0.0a1/docs/designs/sv-agent-open-context.md +123 -0
  59. scaneval-2.0.0a1/docs/designs/sv-completion-bounded-verification.md +127 -0
  60. scaneval-2.0.0a1/docs/designs/sv-review-workflow.md +115 -0
  61. scaneval-2.0.0a1/docs/research/recent-cve-candidates.json +4451 -0
  62. scaneval-2.0.0a1/docs/research/recent-cve-chronology.json +106 -0
  63. scaneval-2.0.0a1/docs/reviews/DATASET_COUNCIL_2026-10-22.json +92 -0
  64. scaneval-2.0.0a1/docs/reviews/DATASET_COUNCIL_2026-10-22.md +76 -0
  65. scaneval-2.0.0a1/docs/specs/CVSS_CALIBRATION_60.md +81 -0
  66. scaneval-2.0.0a1/examples/aggregation-policy.json +21 -0
  67. scaneval-2.0.0a1/examples/dataset_plugin/README.md +25 -0
  68. scaneval-2.0.0a1/examples/dataset_plugin/pyproject.toml +16 -0
  69. scaneval-2.0.0a1/examples/dataset_plugin/scaneval_example_dataset.py +25 -0
  70. scaneval-2.0.0a1/examples/experiment_matrix_fixture.py +83 -0
  71. scaneval-2.0.0a1/examples/gate-policy.json +70 -0
  72. scaneval-2.0.0a1/examples/observer/README.md +152 -0
  73. scaneval-2.0.0a1/examples/observer/python_harness.py +259 -0
  74. scaneval-2.0.0a1/examples/observer/typescript_harness.mts +233 -0
  75. scaneval-2.0.0a1/examples/open_context_fixture.py +85 -0
  76. scaneval-2.0.0a1/pyproject.toml +68 -0
  77. scaneval-2.0.0a1/schema/v2/fixtures/collectors/claude-code-edge-cases.jsonl +12 -0
  78. scaneval-2.0.0a1/schema/v2/fixtures/collectors/claude-code-result.json +19 -0
  79. scaneval-2.0.0a1/schema/v2/fixtures/collectors/claude-code-stream-json-error.jsonl +3 -0
  80. scaneval-2.0.0a1/schema/v2/fixtures/collectors/claude-code-stream-json.jsonl +11 -0
  81. scaneval-2.0.0a1/schema/v2/fixtures/collectors/claude-code-subagent.jsonl +17 -0
  82. scaneval-2.0.0a1/schema/v2/fixtures/collectors/claude-code-transcript.jsonl +32 -0
  83. scaneval-2.0.0a1/schema/v2/fixtures/collectors/codex-exec-edge-cases.jsonl +6 -0
  84. scaneval-2.0.0a1/schema/v2/fixtures/collectors/codex-exec.jsonl +9 -0
  85. scaneval-2.0.0a1/schema/v2/fixtures/trace-event-v2.json +14 -0
  86. scaneval-2.0.0a1/schema/v2/trace-event.schema.json +20 -0
  87. scaneval-2.0.0a1/scripts/check_python_package.py +144 -0
  88. scaneval-2.0.0a1/scripts/check_sv_completion_properties.py +1085 -0
  89. scaneval-2.0.0a1/scripts/oci_ci_path_gate.py +161 -0
  90. scaneval-2.0.0a1/scripts/sanitize_native_trace.py +390 -0
  91. scaneval-2.0.0a1/sdk/typescript/.gitignore +2 -0
  92. scaneval-2.0.0a1/sdk/typescript/package-lock.json +548 -0
  93. scaneval-2.0.0a1/sdk/typescript/package.json +24 -0
  94. scaneval-2.0.0a1/sdk/typescript/src/index.ts +1243 -0
  95. scaneval-2.0.0a1/sdk/typescript/test/observer.test.mjs +934 -0
  96. scaneval-2.0.0a1/sdk/typescript/tsconfig.json +13 -0
  97. scaneval-2.0.0a1/setup.cfg +4 -0
  98. scaneval-2.0.0a1/skills/cve-corpus-review/SKILL.md +56 -0
  99. scaneval-2.0.0a1/skills/cve-corpus-review/agents/openai.yaml +4 -0
  100. scaneval-2.0.0a1/skills/cve-corpus-review/references/evidence-review.md +39 -0
  101. scaneval-2.0.0a1/skills/cve-corpus-review/references/machine-records.md +61 -0
  102. scaneval-2.0.0a1/skills/scanner-adapter-builder/SKILL.md +51 -0
  103. scaneval-2.0.0a1/skills/scanner-adapter-builder/agents/openai.yaml +4 -0
  104. scaneval-2.0.0a1/skills/scanner-adapter-builder/references/failure-patterns.md +149 -0
  105. scaneval-2.0.0a1/skills/scanner-adapter-builder/references/property-verification.md +34 -0
  106. scaneval-2.0.0a1/src/scaneval/__init__.py +13 -0
  107. scaneval-2.0.0a1/src/scaneval/__main__.py +3 -0
  108. scaneval-2.0.0a1/src/scaneval/adapters/__init__.py +30 -0
  109. scaneval-2.0.0a1/src/scaneval/adapters/base.py +535 -0
  110. scaneval-2.0.0a1/src/scaneval/adapters/deepsec.py +3944 -0
  111. scaneval-2.0.0a1/src/scaneval/adapters/llm_harness.py +3312 -0
  112. scaneval-2.0.0a1/src/scaneval/adapters/llm_harness_driver.mts +2160 -0
  113. scaneval-2.0.0a1/src/scaneval/adapters/pi_oci_runner.mts +317 -0
  114. scaneval-2.0.0a1/src/scaneval/adapters/pi_open_context.mts +19 -0
  115. scaneval-2.0.0a1/src/scaneval/adapters/pi_open_context_tools.mjs +506 -0
  116. scaneval-2.0.0a1/src/scaneval/adapters/pi_synthetic_provider.mts +115 -0
  117. scaneval-2.0.0a1/src/scaneval/adapters/pr.py +252 -0
  118. scaneval-2.0.0a1/src/scaneval/adapters/runsortie.py +3279 -0
  119. scaneval-2.0.0a1/src/scaneval/adapters/runsortie_evidence.py +2232 -0
  120. scaneval-2.0.0a1/src/scaneval/adapters/semgrep.py +1081 -0
  121. scaneval-2.0.0a1/src/scaneval/aggregate.py +2548 -0
  122. scaneval-2.0.0a1/src/scaneval/artifacts.py +38 -0
  123. scaneval-2.0.0a1/src/scaneval/benchmark.py +486 -0
  124. scaneval-2.0.0a1/src/scaneval/benchmark_cli.py +61 -0
  125. scaneval-2.0.0a1/src/scaneval/blinding.py +1886 -0
  126. scaneval-2.0.0a1/src/scaneval/cases.py +1573 -0
  127. scaneval-2.0.0a1/src/scaneval/cli.py +1799 -0
  128. scaneval-2.0.0a1/src/scaneval/collectors/__init__.py +545 -0
  129. scaneval-2.0.0a1/src/scaneval/collectors/claude_code.py +1600 -0
  130. scaneval-2.0.0a1/src/scaneval/collectors/codex.py +494 -0
  131. scaneval-2.0.0a1/src/scaneval/collectors/source.py +63 -0
  132. scaneval-2.0.0a1/src/scaneval/conditions.py +624 -0
  133. scaneval-2.0.0a1/src/scaneval/conditions_identity.py +93 -0
  134. scaneval-2.0.0a1/src/scaneval/contracts.py +2695 -0
  135. scaneval-2.0.0a1/src/scaneval/corpus.py +57 -0
  136. scaneval-2.0.0a1/src/scaneval/data/model-cutoffs.json +1717 -0
  137. scaneval-2.0.0a1/src/scaneval/datasets/__init__.py +35 -0
  138. scaneval-2.0.0a1/src/scaneval/datasets/base.py +139 -0
  139. scaneval-2.0.0a1/src/scaneval/datasets/builtin.py +224 -0
  140. scaneval-2.0.0a1/src/scaneval/datasets/cli.py +50 -0
  141. scaneval-2.0.0a1/src/scaneval/datasets/locks/aacr-bench.json +54 -0
  142. scaneval-2.0.0a1/src/scaneval/datasets/locks/martian.json +522 -0
  143. scaneval-2.0.0a1/src/scaneval/datasets/locks/openssf.json +1628 -0
  144. scaneval-2.0.0a1/src/scaneval/datasets/locks/reviewbench.json +1578 -0
  145. scaneval-2.0.0a1/src/scaneval/demo.py +64 -0
  146. scaneval-2.0.0a1/src/scaneval/diagnostics.py +1089 -0
  147. scaneval-2.0.0a1/src/scaneval/evaluator.py +27 -0
  148. scaneval-2.0.0a1/src/scaneval/execution.py +1764 -0
  149. scaneval-2.0.0a1/src/scaneval/experiment.py +507 -0
  150. scaneval-2.0.0a1/src/scaneval/experiment_execution.py +405 -0
  151. scaneval-2.0.0a1/src/scaneval/experiment_report.py +457 -0
  152. scaneval-2.0.0a1/src/scaneval/gate.py +1344 -0
  153. scaneval-2.0.0a1/src/scaneval/identity_policy.py +1278 -0
  154. scaneval-2.0.0a1/src/scaneval/investigation.py +467 -0
  155. scaneval-2.0.0a1/src/scaneval/investigation_html.py +138 -0
  156. scaneval-2.0.0a1/src/scaneval/isolation/__init__.py +275 -0
  157. scaneval-2.0.0a1/src/scaneval/isolation/egress_proxy.py +302 -0
  158. scaneval-2.0.0a1/src/scaneval/isolation/oci.py +1335 -0
  159. scaneval-2.0.0a1/src/scaneval/isolation/public_retrieval.py +556 -0
  160. scaneval-2.0.0a1/src/scaneval/kinds.py +86 -0
  161. scaneval-2.0.0a1/src/scaneval/machine_review.py +299 -0
  162. scaneval-2.0.0a1/src/scaneval/mappings/kinds.json +43 -0
  163. scaneval-2.0.0a1/src/scaneval/materialize.py +1243 -0
  164. scaneval-2.0.0a1/src/scaneval/model_cutoff_projection.py +148 -0
  165. scaneval-2.0.0a1/src/scaneval/model_cutoffs.py +261 -0
  166. scaneval-2.0.0a1/src/scaneval/model_cutoffs_cli.py +36 -0
  167. scaneval-2.0.0a1/src/scaneval/observer/__init__.py +81 -0
  168. scaneval-2.0.0a1/src/scaneval/observer/emitter.py +1795 -0
  169. scaneval-2.0.0a1/src/scaneval/open_context.py +341 -0
  170. scaneval-2.0.0a1/src/scaneval/open_context_evidence.py +285 -0
  171. scaneval-2.0.0a1/src/scaneval/precision.py +929 -0
  172. scaneval-2.0.0a1/src/scaneval/report.py +114 -0
  173. scaneval-2.0.0a1/src/scaneval/resampling.py +93 -0
  174. scaneval-2.0.0a1/src/scaneval/review.py +475 -0
  175. scaneval-2.0.0a1/src/scaneval/runner.py +1257 -0
  176. scaneval-2.0.0a1/src/scaneval/sarif.py +2240 -0
  177. scaneval-2.0.0a1/src/scaneval/schedule.py +277 -0
  178. scaneval-2.0.0a1/src/scaneval/schemas/aggregate-report.schema.json +2011 -0
  179. scaneval-2.0.0a1/src/scaneval/schemas/aggregation-policy.schema.json +131 -0
  180. scaneval-2.0.0a1/src/scaneval/schemas/blinding-map.schema.json +426 -0
  181. scaneval-2.0.0a1/src/scaneval/schemas/case-pack-2.1.schema.json +1172 -0
  182. scaneval-2.0.0a1/src/scaneval/schemas/case-pack.schema.json +257 -0
  183. scaneval-2.0.0a1/src/scaneval/schemas/comparison-report.schema.json +2078 -0
  184. scaneval-2.0.0a1/src/scaneval/schemas/condition-record.schema.json +41 -0
  185. scaneval-2.0.0a1/src/scaneval/schemas/dataset.schema.json +61 -0
  186. scaneval-2.0.0a1/src/scaneval/schemas/evaluation-plan-2.1.schema.json +329 -0
  187. scaneval-2.0.0a1/src/scaneval/schemas/evaluation-plan.schema.json +52 -0
  188. scaneval-2.0.0a1/src/scaneval/schemas/evaluation-schedule.schema.json +647 -0
  189. scaneval-2.0.0a1/src/scaneval/schemas/execution-record-2.1.schema.json +501 -0
  190. scaneval-2.0.0a1/src/scaneval/schemas/execution-record.schema.json +79 -0
  191. scaneval-2.0.0a1/src/scaneval/schemas/experiment-matrix.schema.json +99 -0
  192. scaneval-2.0.0a1/src/scaneval/schemas/gate-decision.schema.json +387 -0
  193. scaneval-2.0.0a1/src/scaneval/schemas/gate-policy.schema.json +436 -0
  194. scaneval-2.0.0a1/src/scaneval/schemas/identity-transformation-manifest.schema.json +136 -0
  195. scaneval-2.0.0a1/src/scaneval/schemas/import-record.schema.json +680 -0
  196. scaneval-2.0.0a1/src/scaneval/schemas/machine-judgments.schema.json +72 -0
  197. scaneval-2.0.0a1/src/scaneval/schemas/precision-estimate.schema.json +807 -0
  198. scaneval-2.0.0a1/src/scaneval/schemas/precision-reviews.schema.json +96 -0
  199. scaneval-2.0.0a1/src/scaneval/schemas/precision-sample.schema.json +667 -0
  200. scaneval-2.0.0a1/src/scaneval/schemas/review-decisions.schema.json +40 -0
  201. scaneval-2.0.0a1/src/scaneval/schemas/review-record.schema.json +21 -0
  202. scaneval-2.0.0a1/src/scaneval/schemas/run-config-2.1.schema.json +275 -0
  203. scaneval-2.0.0a1/src/scaneval/schemas/run-config.schema.json +29 -0
  204. scaneval-2.0.0a1/src/scaneval/schemas/run-manifest-2.1.schema.json +599 -0
  205. scaneval-2.0.0a1/src/scaneval/schemas/run-manifest.schema.json +140 -0
  206. scaneval-2.0.0a1/src/scaneval/schemas/scan-request.schema.json +52 -0
  207. scaneval-2.0.0a1/src/scaneval/schemas/scan-result-2.1.schema.json +295 -0
  208. scaneval-2.0.0a1/src/scaneval/schemas/scan-result.schema.json +73 -0
  209. scaneval-2.0.0a1/src/scaneval/schemas/severity-report.schema.json +1158 -0
  210. scaneval-2.0.0a1/src/scaneval/schemas/trace-event.schema.json +20 -0
  211. scaneval-2.0.0a1/src/scaneval/scoring.py +379 -0
  212. scaneval-2.0.0a1/src/scaneval/severity.py +422 -0
  213. scaneval-2.0.0a1/src/scaneval/source.py +20 -0
  214. scaneval-2.0.0a1/src/scaneval/trace.py +80 -0
  215. scaneval-2.0.0a1/src/scaneval.egg-info/PKG-INFO +145 -0
  216. scaneval-2.0.0a1/src/scaneval.egg-info/SOURCES.txt +310 -0
  217. scaneval-2.0.0a1/src/scaneval.egg-info/dependency_links.txt +1 -0
  218. scaneval-2.0.0a1/src/scaneval.egg-info/entry_points.txt +2 -0
  219. scaneval-2.0.0a1/src/scaneval.egg-info/requires.txt +9 -0
  220. scaneval-2.0.0a1/src/scaneval.egg-info/top_level.txt +1 -0
  221. scaneval-2.0.0a1/tests/conftest.py +49 -0
  222. scaneval-2.0.0a1/tests/fixtures/deepsec-capture-matrix.json +24 -0
  223. scaneval-2.0.0a1/tests/fixtures/runsortie/fake_runsortie.py +1392 -0
  224. scaneval-2.0.0a1/tests/fixtures/runsortie/fake_tools.py +174 -0
  225. scaneval-2.0.0a1/tests/fixtures/sarif/codeql.sarif +174 -0
  226. scaneval-2.0.0a1/tests/fixtures/sarif/semgrep-shell.json +23 -0
  227. scaneval-2.0.0a1/tests/fixtures/sarif/semgrep.sarif +117 -0
  228. scaneval-2.0.0a1/tests/fixtures/sv-completion.json +71 -0
  229. scaneval-2.0.0a1/tests/fixtures/sv-review-workflow-summary.json +906 -0
  230. scaneval-2.0.0a1/tests/node/sv_pi_oci.test.mjs +283 -0
  231. scaneval-2.0.0a1/tests/node/sv_runtime_dependencies.test.mjs +161 -0
  232. scaneval-2.0.0a1/tests/test_ci_oci_path_gate.py +177 -0
  233. scaneval-2.0.0a1/tests/test_codex_guard_docker.py +347 -0
  234. scaneval-2.0.0a1/tests/test_codex_quota_buckets.py +263 -0
  235. scaneval-2.0.0a1/tests/test_codex_quota_guard.py +820 -0
  236. scaneval-2.0.0a1/tests/test_dataset_adapters.py +252 -0
  237. scaneval-2.0.0a1/tests/test_dataset_benchmark.py +643 -0
  238. scaneval-2.0.0a1/tests/test_identifier_evidence_boundaries.py +113 -0
  239. scaneval-2.0.0a1/tests/test_identifier_python_boundaries.py +134 -0
  240. scaneval-2.0.0a1/tests/test_identifier_run_boundaries.py +123 -0
  241. scaneval-2.0.0a1/tests/test_identifier_schema_boundaries.py +154 -0
  242. scaneval-2.0.0a1/tests/test_local_command_cleanup.py +223 -0
  243. scaneval-2.0.0a1/tests/test_machine_review.py +188 -0
  244. scaneval-2.0.0a1/tests/test_model_cutoff_projection.py +410 -0
  245. scaneval-2.0.0a1/tests/test_model_cutoffs.py +384 -0
  246. scaneval-2.0.0a1/tests/test_native_trace_sanitizer.py +90 -0
  247. scaneval-2.0.0a1/tests/test_sv_completion_properties.py +129 -0
  248. scaneval-2.0.0a1/tests/test_v2_adapter_modes.py +345 -0
  249. scaneval-2.0.0a1/tests/test_v2_aggregate.py +3181 -0
  250. scaneval-2.0.0a1/tests/test_v2_artifact_recovery.py +49 -0
  251. scaneval-2.0.0a1/tests/test_v2_blinding.py +3040 -0
  252. scaneval-2.0.0a1/tests/test_v2_cases.py +2981 -0
  253. scaneval-2.0.0a1/tests/test_v2_cli.py +261 -0
  254. scaneval-2.0.0a1/tests/test_v2_cli_corpus.py +1773 -0
  255. scaneval-2.0.0a1/tests/test_v2_collectors.py +2381 -0
  256. scaneval-2.0.0a1/tests/test_v2_condition_history.py +124 -0
  257. scaneval-2.0.0a1/tests/test_v2_condition_identity.py +187 -0
  258. scaneval-2.0.0a1/tests/test_v2_condition_reporting.py +299 -0
  259. scaneval-2.0.0a1/tests/test_v2_conditions.py +672 -0
  260. scaneval-2.0.0a1/tests/test_v2_contracts.py +1884 -0
  261. scaneval-2.0.0a1/tests/test_v2_contracts_21.py +418 -0
  262. scaneval-2.0.0a1/tests/test_v2_deepsec.py +6054 -0
  263. scaneval-2.0.0a1/tests/test_v2_diagnostics.py +1443 -0
  264. scaneval-2.0.0a1/tests/test_v2_execution.py +3484 -0
  265. scaneval-2.0.0a1/tests/test_v2_experiment_cli.py +57 -0
  266. scaneval-2.0.0a1/tests/test_v2_experiment_docker.py +78 -0
  267. scaneval-2.0.0a1/tests/test_v2_experiment_execution.py +783 -0
  268. scaneval-2.0.0a1/tests/test_v2_experiment_freeze.py +150 -0
  269. scaneval-2.0.0a1/tests/test_v2_experiment_matrix.py +158 -0
  270. scaneval-2.0.0a1/tests/test_v2_experiment_report.py +203 -0
  271. scaneval-2.0.0a1/tests/test_v2_gate.py +3835 -0
  272. scaneval-2.0.0a1/tests/test_v2_identity_exports.py +451 -0
  273. scaneval-2.0.0a1/tests/test_v2_identity_policy.py +935 -0
  274. scaneval-2.0.0a1/tests/test_v2_investigation.py +612 -0
  275. scaneval-2.0.0a1/tests/test_v2_investigation_cli.py +48 -0
  276. scaneval-2.0.0a1/tests/test_v2_isolation.py +1489 -0
  277. scaneval-2.0.0a1/tests/test_v2_isolation_docker.py +1235 -0
  278. scaneval-2.0.0a1/tests/test_v2_kinds.py +96 -0
  279. scaneval-2.0.0a1/tests/test_v2_llm_harness.py +4890 -0
  280. scaneval-2.0.0a1/tests/test_v2_materialize.py +1345 -0
  281. scaneval-2.0.0a1/tests/test_v2_native_mapping.py +94 -0
  282. scaneval-2.0.0a1/tests/test_v2_numeric_readers.py +125 -0
  283. scaneval-2.0.0a1/tests/test_v2_observer.py +3534 -0
  284. scaneval-2.0.0a1/tests/test_v2_observer_parity.py +2971 -0
  285. scaneval-2.0.0a1/tests/test_v2_observer_python.py +556 -0
  286. scaneval-2.0.0a1/tests/test_v2_open_context.py +350 -0
  287. scaneval-2.0.0a1/tests/test_v2_open_context_docker.py +168 -0
  288. scaneval-2.0.0a1/tests/test_v2_open_context_evidence.py +180 -0
  289. scaneval-2.0.0a1/tests/test_v2_open_context_reporting.py +17 -0
  290. scaneval-2.0.0a1/tests/test_v2_open_context_runner.py +157 -0
  291. scaneval-2.0.0a1/tests/test_v2_pr.py +765 -0
  292. scaneval-2.0.0a1/tests/test_v2_precision.py +1342 -0
  293. scaneval-2.0.0a1/tests/test_v2_public_retrieval.py +798 -0
  294. scaneval-2.0.0a1/tests/test_v2_public_retrieval_deadline_fragments.py +91 -0
  295. scaneval-2.0.0a1/tests/test_v2_repository_hygiene.py +91 -0
  296. scaneval-2.0.0a1/tests/test_v2_resampling.py +77 -0
  297. scaneval-2.0.0a1/tests/test_v2_review.py +857 -0
  298. scaneval-2.0.0a1/tests/test_v2_runner.py +1053 -0
  299. scaneval-2.0.0a1/tests/test_v2_runner_inputs.py +602 -0
  300. scaneval-2.0.0a1/tests/test_v2_runsortie.py +2447 -0
  301. scaneval-2.0.0a1/tests/test_v2_sarif.py +2550 -0
  302. scaneval-2.0.0a1/tests/test_v2_schedule.py +533 -0
  303. scaneval-2.0.0a1/tests/test_v2_scoring.py +701 -0
  304. scaneval-2.0.0a1/tests/test_v2_semgrep.py +1772 -0
  305. scaneval-2.0.0a1/tests/test_v2_semgrep_full_coverage.py +287 -0
  306. scaneval-2.0.0a1/tests/test_v2_severity.py +427 -0
  307. scaneval-2.0.0a1/tests/test_v2_sv_open_context.py +846 -0
  308. scaneval-2.0.0a1/tests/test_v2_sv_open_context_docker.py +219 -0
  309. scaneval-2.0.0a1/tests/test_v2_trace_contract.py +41 -0
  310. scaneval-2.0.0a1/tests/test_v2_trace_reader.py +62 -0
  311. scaneval-2.0.0a1/tools/codex_guard_docker.py +334 -0
  312. scaneval-2.0.0a1/tools/codex_quota_guard.py +829 -0
@@ -0,0 +1,155 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ test:
18
+ name: Python ${{ matrix.python }} and TypeScript
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 20
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ python: ['3.11', '3.13', '3.14']
25
+ env:
26
+ PYTHONDONTWRITEBYTECODE: '1'
27
+ SEMGREP_SEND_METRICS: 'off'
28
+ steps:
29
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30
+ with:
31
+ persist-credentials: false
32
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
33
+ with:
34
+ python-version: ${{ matrix.python }}
35
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
36
+ with:
37
+ node-version: '24'
38
+ cache: npm
39
+ cache-dependency-path: sdk/typescript/package-lock.json
40
+ - name: Install test dependencies
41
+ run: |
42
+ python -m pip install -e '.[dev]' build 'semgrep==1.177.0'
43
+ npm ci --prefix sdk/typescript
44
+ - name: TypeScript tests and build
45
+ run: npm test --prefix sdk/typescript
46
+ - name: Python tests including Observer parity
47
+ # Tests use fixtures and mock runners, never paid models. Tests requiring
48
+ # external harness checkouts or preserved private bundles report skips.
49
+ run: python -m pytest -q -rs
50
+ - name: Build wheel
51
+ run: python -m build --wheel --outdir "$RUNNER_TEMP/scaneval-dist"
52
+ - name: Installed-wheel demo and replay
53
+ working-directory: ${{ runner.temp }}
54
+ env:
55
+ PYTHONPATH: ''
56
+ run: |
57
+ python -m venv "$RUNNER_TEMP/scaneval-wheel-env"
58
+ "$RUNNER_TEMP/scaneval-wheel-env/bin/python" -m pip install "$RUNNER_TEMP"/scaneval-dist/*.whl
59
+ "$RUNNER_TEMP/scaneval-wheel-env/bin/scaneval" demo "$RUNNER_TEMP/scaneval-demo"
60
+ "$RUNNER_TEMP/scaneval-wheel-env/bin/scaneval" replay "$RUNNER_TEMP/scaneval-demo" --output "$RUNNER_TEMP/scaneval-replay.json"
61
+ cmp "$RUNNER_TEMP/scaneval-demo/evaluation.json" "$RUNNER_TEMP/scaneval-replay.json"
62
+
63
+ runtime-dependencies:
64
+ name: Audited SV-Agent runtime dependencies
65
+ runs-on: ubuntu-latest
66
+ timeout-minutes: 10
67
+ env:
68
+ PI_OFFLINE: '1'
69
+ PI_SKIP_VERSION_CHECK: '1'
70
+ steps:
71
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
72
+ with:
73
+ persist-credentials: false
74
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
75
+ with:
76
+ node-version: '26.7.0'
77
+ cache: npm
78
+ cache-dependency-path: containers/sv-agent/package-lock.json
79
+ - name: Install the image's runtime dependencies
80
+ run: npm ci --prefix containers/sv-agent --omit=dev --ignore-scripts --engine-strict
81
+ - name: Audit both dependency locks
82
+ run: |
83
+ npm audit --prefix containers/sv-agent --omit=dev --audit-level=low
84
+ npm audit --prefix sdk/typescript --package-lock-only --audit-level=low
85
+ - name: Exercise the native CLI, glob selection, and proxy transport
86
+ # Real installed Pi and dependencies against local fixtures, with no model calls.
87
+ run: node --test tests/node/sv_runtime_dependencies.test.mjs
88
+
89
+ oci_path_gate:
90
+ name: Decide whether OCI integration is relevant
91
+ runs-on: ubuntu-latest
92
+ timeout-minutes: 5
93
+ outputs:
94
+ run_oci: ${{ steps.filter.outputs.run_oci }}
95
+ steps:
96
+ # pull_request checks out GitHub's merge ref. Depth two contains the merge commit and its
97
+ # base parent, so HEAD^..HEAD is the complete PR change, not merely its last commit.
98
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
99
+ with:
100
+ fetch-depth: 2
101
+ persist-credentials: false
102
+ - name: Match OCI-relevant paths
103
+ id: filter
104
+ env:
105
+ EVENT_NAME: ${{ github.event_name }}
106
+ run: |
107
+ set -euo pipefail
108
+ decision="$(python3 scripts/oci_ci_path_gate.py --event-name "$EVENT_NAME")"
109
+ case "$decision" in
110
+ true|false) ;;
111
+ *) echo "OCI path gate returned an invalid decision: $decision" >&2; exit 1 ;;
112
+ esac
113
+ echo "run_oci=$decision" >> "$GITHUB_OUTPUT"
114
+
115
+ oci-integration:
116
+ name: OCI backend against a real Docker engine
117
+ needs: oci_path_gate
118
+ # A failed filter must surface as a failed required check, never as a silently skipped Docker
119
+ # run. Pushes to main and workflow_dispatch return true without consulting the diff.
120
+ if: ${{ always() && (needs.oci_path_gate.result != 'success' || needs.oci_path_gate.outputs.run_oci != 'false') }}
121
+ runs-on: ubuntu-latest
122
+ timeout-minutes: 20
123
+ env:
124
+ PYTHONDONTWRITEBYTECODE: '1'
125
+ # Without this the module skips when no engine or image is present; here that is a failure.
126
+ SCANEVAL_REQUIRE_DOCKER: '1'
127
+ steps:
128
+ - name: Require a successful path decision
129
+ if: ${{ needs.oci_path_gate.result != 'success' }}
130
+ run: |
131
+ echo "The OCI path gate failed; refusing to hide the Docker check." >&2
132
+ exit 1
133
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
134
+ with:
135
+ persist-credentials: false
136
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
137
+ with:
138
+ python-version: '3.13'
139
+ - name: Install test dependencies
140
+ run: python -m pip install -e '.[dev]'
141
+ - name: Describe the engine
142
+ # model_provider_only needs an engine that applies gateway_mode_ipv4=isolated; the record
143
+ # of which engine ran is here when that test says it did not.
144
+ run: |
145
+ docker version
146
+ docker info
147
+ - name: Pull the pinned images
148
+ # The backend never pulls an image, so the tests use only what is already present.
149
+ run: |
150
+ docker pull python:3.12-slim@sha256:2f17fc044b579bab302c2e8054d3a686e2cb9a83de48e70534b94cd8ebbe06a9
151
+ docker pull semgrep/semgrep:1.177.0@sha256:acaac22ffc7b7cc5926de0751b223bce0b2491c33d18422fa72f632c78d81198
152
+ - name: OCI integration tests
153
+ # Real containers, local fixture services, and benign example.com retrieval; no model
154
+ # or target application is called. Native Linux also checks cross-UID capture reads.
155
+ run: python -m pytest -q -rs tests/test_v2_isolation_docker.py tests/test_v2_open_context_docker.py tests/test_v2_experiment_docker.py
@@ -0,0 +1,116 @@
1
+ name: Python alpha package
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - '.github/workflows/publish-packages.yml'
7
+ - 'pyproject.toml'
8
+ - 'MANIFEST.in'
9
+ - 'README_PYPI.md'
10
+ - 'LICENSE'
11
+ - 'src/**'
12
+ - 'scripts/check_python_package.py'
13
+ push:
14
+ branches: [main]
15
+ paths:
16
+ - '.github/workflows/publish-packages.yml'
17
+ - 'pyproject.toml'
18
+ - 'MANIFEST.in'
19
+ - 'README_PYPI.md'
20
+ - 'LICENSE'
21
+ - 'src/**'
22
+ - 'scripts/check_python_package.py'
23
+ workflow_dispatch:
24
+ inputs:
25
+ publish:
26
+ description: Publish the verified Python artifacts (requires PyPI trusted-publisher setup)
27
+ type: boolean
28
+ default: false
29
+
30
+ permissions:
31
+ contents: read
32
+
33
+ concurrency:
34
+ group: python-alpha-package-${{ github.ref }}
35
+ cancel-in-progress: false
36
+
37
+ jobs:
38
+ python-artifacts:
39
+ name: Python wheel and source archive
40
+ runs-on: ubuntu-latest
41
+ timeout-minutes: 10
42
+ steps:
43
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
44
+ with:
45
+ persist-credentials: false
46
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
47
+ with:
48
+ python-version: '3.11'
49
+ - name: Build and validate distribution metadata
50
+ run: |
51
+ python -m pip install build twine
52
+ python - <<'PY'
53
+ import tomllib
54
+ from packaging.version import Version
55
+ with open('pyproject.toml', 'rb') as source:
56
+ project = tomllib.load(source)['project']
57
+ assert project['name'] == 'scaneval'
58
+ assert Version(project['version']).is_prerelease, 'This workflow publishes alpha releases only'
59
+ PY
60
+ python -m build --outdir "$RUNNER_TEMP/python-dist"
61
+ python -m twine check --strict "$RUNNER_TEMP"/python-dist/*
62
+ - name: Install and exercise the exact wheel and source archive
63
+ run: |
64
+ for artifact in "$RUNNER_TEMP"/python-dist/*; do
65
+ python scripts/check_python_package.py "$artifact"
66
+ done
67
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
68
+ with:
69
+ name: python-dist-${{ github.sha }}
70
+ path: ${{ runner.temp }}/python-dist/*
71
+ if-no-files-found: error
72
+ retention-days: 14
73
+
74
+ verified-main:
75
+ name: Require successful main CI before publishing
76
+ if: github.event_name == 'workflow_dispatch' && inputs.publish
77
+ runs-on: ubuntu-latest
78
+ timeout-minutes: 5
79
+ permissions:
80
+ contents: read
81
+ actions: read
82
+ steps:
83
+ - name: Refuse publication outside main or before its CI passes
84
+ env:
85
+ GH_TOKEN: ${{ github.token }}
86
+ REPOSITORY: ${{ github.repository }}
87
+ RELEASE_SHA: ${{ github.sha }}
88
+ RELEASE_REF: ${{ github.ref }}
89
+ run: |
90
+ test "$RELEASE_REF" = refs/heads/main
91
+ gh api --method GET "repos/$REPOSITORY/actions/workflows/ci.yml/runs" \
92
+ -f head_sha="$RELEASE_SHA" -f status=success -f event=push > "$RUNNER_TEMP/ci.json"
93
+ python3 - <<'PY'
94
+ import json, os
95
+ from pathlib import Path
96
+ runs = json.loads(Path(os.environ['RUNNER_TEMP'], 'ci.json').read_text())['workflow_runs']
97
+ assert any(run['head_sha'] == os.environ['RELEASE_SHA'] and run['conclusion'] == 'success'
98
+ and run['event'] == 'push' for run in runs), 'Current main CI has not passed'
99
+ PY
100
+
101
+ publish-pypi:
102
+ name: Publish Python alpha to PyPI
103
+ needs: [python-artifacts, verified-main]
104
+ if: github.event_name == 'workflow_dispatch' && inputs.publish
105
+ runs-on: ubuntu-latest
106
+ timeout-minutes: 5
107
+ environment: pypi
108
+ permissions:
109
+ contents: read
110
+ id-token: write
111
+ steps:
112
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
113
+ with:
114
+ name: python-dist-${{ github.sha }}
115
+ path: dist
116
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
@@ -0,0 +1,35 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.egg-info/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+
11
+ # Rust
12
+ target/
13
+
14
+ # Node
15
+ node_modules/
16
+
17
+ # IDE
18
+ .vscode/
19
+ .idea/
20
+
21
+ # OS
22
+ .DS_Store
23
+ Thumbs.db
24
+
25
+ # ScanEval
26
+ .repos/
27
+ results/
28
+ *.html
29
+
30
+ # Scanner artifacts
31
+ .securevibes/
32
+ .claude/
33
+
34
+ # case-build scratch dirs
35
+ .*_build/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ScanEval contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ include LICENSE README.md README_PYPI.md pyproject.toml .gitignore
2
+ recursive-include src *.py *.json *.mts *.mjs
3
+ recursive-include docs *.md *.json
4
+ recursive-include examples *.py *.mts *.md *.json *.toml
5
+ recursive-include schema *.json *.jsonl
6
+ recursive-include corpus *.md *.json
7
+ recursive-include scripts *.py
8
+ recursive-include tools *.py
9
+ recursive-include tests *.py *.json *.sarif *.mjs
10
+ recursive-include sdk/typescript *.json *.ts *.mjs *.md LICENSE
11
+ include sdk/typescript/.gitignore
12
+ recursive-include containers/sv-agent Dockerfile Dockerfile.dockerignore *.json *.mjs *.md *.sh
13
+ recursive-include skills *.md *.yaml
14
+ recursive-include .github *.yml
15
+
16
+ # Source archives carry runnable examples and test fixtures, never local runs or caches.
17
+ prune .git
18
+ prune .repos
19
+ prune results
20
+ prune build
21
+ prune dist
22
+ prune .venv
23
+ prune .pytest_cache
24
+ prune .claude
25
+ prune .securevibes
26
+ prune sdk/typescript/node_modules
27
+ prune sdk/typescript/dist
28
+ prune containers/sv-agent/node_modules
29
+ global-exclude __pycache__ *.py[cod] .DS_Store
@@ -0,0 +1,145 @@
1
+ Metadata-Version: 2.4
2
+ Name: scaneval
3
+ Version: 2.0.0a1
4
+ Summary: Alpha framework for reproducible security-scanner evaluation and observability.
5
+ Author: ScanEval contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Har1sh-k/scaneval
8
+ Project-URL: Repository, https://github.com/Har1sh-k/scaneval
9
+ Project-URL: Documentation, https://github.com/Har1sh-k/scaneval/blob/main/docs/INITIAL_BUILD.md
10
+ Project-URL: Issues, https://github.com/Har1sh-k/scaneval/issues
11
+ Keywords: security,scanner,evaluation,benchmark,observability
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: POSIX
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Security
23
+ Classifier: Topic :: Software Development :: Testing
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: jsonschema<5,>=4.23
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0; extra == "dev"
30
+ Requires-Dist: PyYAML>=6.0; extra == "dev"
31
+ Requires-Dist: ruamel.yaml>=0.18; extra == "dev"
32
+ Provides-Extra: official-adapters
33
+ Requires-Dist: semgrep>=1.77.0; extra == "official-adapters"
34
+ Dynamic: license-file
35
+
36
+ # ScanEval
37
+
38
+ ScanEval evaluates structured security-scanner results against a versioned plan and
39
+ supplied review decisions. Import the Python package and call
40
+ `scaneval.evaluate(plan, result, decisions)` to produce an evaluation report offline.
41
+ The same distribution includes a CLI, versioned data contracts, replay, local reports,
42
+ and optional tracing through `scaneval.observer`.
43
+
44
+ **Alpha version: `2.0.0a1`.** No benchmark results or scanner comparisons are published.
45
+ The selected corpus contains 50 CVEs, but fixed controls remain unvalidated and scanner
46
+ miss rates remain unmeasured. Live scanner integrations need separate installations and
47
+ configuration. The default SV-Agent harness pin cannot yet produce a completed
48
+ source-scan score. See the
49
+ [current capabilities and limits](https://github.com/Har1sh-k/scaneval/blob/main/README.md#current-limits).
50
+
51
+ ## Install and evaluate
52
+
53
+ Requires Python 3.11 or newer. Source materialization also requires Git. From a virtual
54
+ environment on macOS or Linux:
55
+
56
+ ```bash
57
+ python -m pip install "scaneval==2.0.0a1"
58
+ ```
59
+
60
+ Load your saved ScanEval evaluation plan, normalized scan result, and review decisions:
61
+
62
+ ```python
63
+ import json
64
+ from pathlib import Path
65
+ import scaneval
66
+
67
+ plan = json.loads(Path("plan.json").read_text(encoding="utf-8"))
68
+ result = json.loads(Path("result.json").read_text(encoding="utf-8"))
69
+ decisions = json.loads(Path("decisions.json").read_text(encoding="utf-8"))
70
+
71
+ report = scaneval.evaluate(plan, result, decisions)
72
+ print(json.dumps(report, indent=2))
73
+ ```
74
+
75
+ Scoring requires structured saved records and supplied finding-review decisions bound to
76
+ those records. The plan assigns targets and controls; the decisions say which findings
77
+ establish their alleged issues. Unreviewed findings remain unresolved. The evaluation API
78
+ validates these inputs and computes scores; producing scanner findings and adjudicating
79
+ natural-language allegations are separate steps.
80
+
81
+ ## Try the offline demo
82
+
83
+ ```bash
84
+ scaneval demo demo-run
85
+ scaneval replay demo-run --output demo-replay.json
86
+ ```
87
+
88
+ Open `demo-run/report.html` locally. The demo uses fabricated evaluator fixtures and
89
+ makes no scanner or model calls. Output paths must be new. Run `scaneval --help` for
90
+ commands; the
91
+ [execution guide](https://github.com/Har1sh-k/scaneval/blob/main/docs/INITIAL_BUILD.md)
92
+ explains scanner configuration, review, and saved evidence.
93
+
94
+ ## Instrument a Python harness
95
+
96
+ The public Python SDK is available from `scaneval.observer`. Emit events at the model,
97
+ tool, context, and finding boundaries your harness exposes:
98
+
99
+ ```python
100
+ from scaneval.observer import Observer
101
+
102
+ events = []
103
+ observer = Observer(
104
+ mode="metadata",
105
+ sink=events.append,
106
+ run_id="example-run",
107
+ producer_id="my-harness",
108
+ )
109
+ observer.emit(
110
+ type="model.request",
111
+ capture_status="complete",
112
+ call_id="call-1",
113
+ metadata={"model": "example-model"},
114
+ )
115
+ observer.flush()
116
+ observer.close()
117
+ ```
118
+
119
+ This example records one event in memory; it calls no model. Recording defaults to
120
+ `off` unless the caller chooses a mode. Capture gaps remain explicit, and traces cannot
121
+ prove hidden reasoning. The
122
+ [Observer SDK guide](https://github.com/Har1sh-k/scaneval/blob/main/docs/OBSERVER_SDK.md)
123
+ describes sinks, recording modes, and capture states. This Observer is part of `scaneval`;
124
+ no separate Python Observer distribution is needed. A
125
+ [TypeScript SDK](https://github.com/Har1sh-k/scaneval/tree/main/sdk/typescript)
126
+ shares the trace contract and remains available as source. This release publishes only
127
+ the Python `scaneval` distribution.
128
+
129
+ ## Cases, datasets, and execution limits
130
+
131
+ Start with the
132
+ [selected CVE corpus](https://github.com/Har1sh-k/scaneval/blob/main/corpus/diverse/README.md),
133
+ [bring your own corpus](https://github.com/Har1sh-k/scaneval/blob/main/docs/BRING_YOUR_OWN_CORPUS.md),
134
+ or [dataset adapters](https://github.com/Har1sh-k/scaneval/blob/main/docs/DATASET_ADAPTERS.md).
135
+ Scoring uses supplied review decisions; unreviewed findings remain unresolved.
136
+
137
+ The local execution backend runs scanners as the operator and enforces no isolation.
138
+ The OCI backend supports specific adapters and configurations; read the
139
+ [threat model](https://github.com/Har1sh-k/scaneval/blob/main/docs/THREAT_MODEL.md)
140
+ before live runs. Keep scanner outputs, private findings, credentials, and content traces
141
+ local.
142
+
143
+ [Source and issues](https://github.com/Har1sh-k/scaneval) are on GitHub. ScanEval is
144
+ [MIT licensed](https://github.com/Har1sh-k/scaneval/blob/main/LICENSE); external scanners
145
+ and source snapshots retain their own licenses.
@@ -0,0 +1,149 @@
1
+ # ScanEval
2
+
3
+ ScanEval evaluates security scanners on versioned cases and records how instrumented harnesses reach their findings. Scoring uses structured outputs and recorded review decisions. Static corpus labels can be assessed separately through evidence-bound machine review.
4
+
5
+ > Alpha (`2.0.0a1`). No benchmark results are published. The [selected CVE corpus](corpus/diverse/README.md) contains 50 CVEs from 32 repositories across seven target languages: 9 Critical, 13 High, 20 Medium and 8 Low by the documented published-CVSS policy. Its 48 pinned vulnerable exports have mechanical checks and a separate machine-review workflow for static labels. Selection emphasizes contextual security reasoning; scanner miss rates remain unmeasured. Fixed controls remain unvalidated. Scanner outputs and traces stay local.
6
+
7
+ ## Python alpha package
8
+
9
+ The planned PyPI release is `scaneval==2.0.0a1`; publication is pending. The Python distribution includes the evaluation API, CLI, and optional tracing through `scaneval.observer`. After publication, install the alpha:
10
+
11
+ ```bash
12
+ python -m pip install scaneval==2.0.0a1
13
+ ```
14
+
15
+ ```python
16
+ import scaneval
17
+
18
+ report = scaneval.evaluate(plan, result, decisions)
19
+ ```
20
+
21
+ The arguments are structured saved ScanEval records: an evaluation plan, normalized scanner result, and supplied review decisions bound to those records. Scoring is offline; scanner execution and finding adjudication are separate steps. See the [Python package guide](README_PYPI.md) for loading the records and the [Observer guide](docs/OBSERVER_SDK.md) for optional instrumentation. The TypeScript Observer remains available as source; this release publishes only the Python `scaneval` distribution. [Release instructions](docs/RELEASING.md) cover artifact verification and PyPI publishing. Use a source checkout for the corpus, examples, and development workflow below.
22
+
23
+ ## Quick start
24
+
25
+ Requires Git and Python 3.11+. Live runs also need the configured scanner.
26
+ From a terminal on macOS or Linux:
27
+
28
+ ```bash
29
+ git clone https://github.com/Har1sh-k/scaneval.git
30
+ cd scaneval
31
+ python3 -m venv .venv
32
+ source .venv/bin/activate
33
+ python -m pip install -e ".[dev]"
34
+ scaneval demo results/diagnostic-demo
35
+ scaneval replay results/diagnostic-demo --output results/diagnostic-replay.json
36
+ # Open results/diagnostic-demo/report.html locally.
37
+ ```
38
+
39
+ The demo uses fabricated evaluator fixtures, not a live scanner or admitted CVEs. It exercises scoring without model calls. Output paths must be new.
40
+
41
+ Start with the [CVE corpus](corpus/diverse/README.md) for the 50 curated cases, severity sources, selection rationale and machine review. [Dataset adapters](docs/DATASET_ADAPTERS.md) add separate PR-review and CVE-detection tracks for AACR-Bench, ReviewBench, Martian, OpenSSF, and your own datasets. The [execution guide](docs/INITIAL_BUILD.md#run-configuration) explains scanner configuration and review. To supply your own security fixes, findings, or documents as case packs, follow [bring your own corpus](docs/BRING_YOUR_OWN_CORPUS.md).
42
+
43
+ ## Evaluation
44
+
45
+ One scan can cover several targets on the same input. A finding needs an accepted security allegation, not just a matching line and vulnerability category. Unreviewed findings remain unresolved; they are not automatically false positives.
46
+
47
+ The scorer reports known-target detection, recall within review budgets, and false allegations against assigned fixed/safe controls. Reviewed precision is estimated separately, from a seeded, human-reviewed sample of delivered claims. Unavailable controls do not become a zero false-alarm rate. Errors and incomplete scans remain distinct from successful scans with no findings. Recorded decisions can be replayed offline.
48
+
49
+ | Command | Purpose |
50
+ |---|---|
51
+ | `scaneval validate <kind> <path>` | Validate a versioned contract. |
52
+ | `scaneval demo <new dir>` | Create the fabricated conformance bundle. No scanner or model runs. |
53
+ | `scaneval score --plan --result --decisions` | Score separately stored records. |
54
+ | `scaneval replay <bundle>` | Recompute a saved bundle offline. |
55
+ | `scaneval report <bundle> --output` | Render a standalone HTML report. |
56
+ | `scaneval investigate <run> --output <new-directory>` | Export a local investigation view and JSON with judgments, trace links, capture states, and artifact bindings ([guide](docs/INVESTIGATION.md)). |
57
+ | `scaneval corpus init\|add-snapshot\|import\|validate\|approve\|admit\|disposition` | Prepare case packs, run mechanical checks, and record explicit reviews and admissions. |
58
+ | `scaneval corpus machine-prepare\|machine-record\|machine-check` | Prepare evidence packets and validate machine judgments of static CVE labels without HITL. |
59
+ | `scaneval corpus add-change-set\|pr-scope\|canonical` | Declare a base/head change set, state which targets and controls are scored in its PR review, and group records by canonical root cause. |
60
+ | `scaneval plan --pack --snapshot-id --tree-hash --output` | Build an evaluation plan for one materialized input, or with `--mode pr --change-set-id` and the hashes that identify it, the PR plan of a change set. |
61
+ | `scaneval run <config> --output <new dir>` | Run a frozen configuration and save its artifacts. |
62
+ | `scaneval matrix freeze\|run\|report` | Freeze and execute the three evaluation conditions, retaining missingness and paired effects ([guide and diagnostic fixture](docs/EXPERIMENT_MATRIX.md)). |
63
+ | `scaneval dataset list\|fetch\|import\|validate\|inspect` | Load a pinned public dataset, native JSON, or an installed Python dataset adapter ([guide](docs/DATASET_ADAPTERS.md)). |
64
+ | `scaneval benchmark plan\|run\|judge-packet\|score` | Evaluate imported datasets with existing scanner adapters, frozen schedules, and supplied machine judgments. |
65
+ | `scaneval blinding check\|review` | Dry-run a metadata blinding map against its snapshots, and record a named review of it. |
66
+ | `scaneval import sarif <log> --pack --snapshot-id --tree-hash --system-id --output` | Import one run of a saved SARIF 2.1.0 log into a new bundle for review, offline. |
67
+ | `scaneval review init\|record\|approve\|status` | Prepare and record the review of an invocation bundle. |
68
+ | `scaneval diagnose context-coverage <bundle>` | Compare captured context spans with labeled targets. Does not change scores. |
69
+ | `scaneval condition <bundle>... [--output]` | Inspect saved condition evidence and separate system/policy/status coverage, offline. |
70
+ | `scaneval aggregate <run dir>... --output` | Weight every scheduled assignment of saved runs into corpus metrics with cluster-bootstrap intervals. |
71
+ | `scaneval severity <run dir>... --pack --output [--html]` | Compare adjudicated claimed severity with reference CVSS, with coverage, provenance and offline replay. See [severity calibration](docs/SEVERITY.md). |
72
+ | `scaneval aggregate <run dir>... --by-condition --output` | Report separate condition/status/policy strata, complete missingness, and descriptive target outcomes. |
73
+ | `scaneval compare <run dir>... --baseline --candidate --output` | Compare two systems assigned the same frozen work, with paired intervals. Decides no promotion. |
74
+ | `scaneval precision sample\|queue\|record\|estimate` | Sample delivered claims from saved runs, record human reviews, and estimate reviewed precision. Does not change scores. |
75
+ | `scaneval gate --policy --comparison --output` | Hold a comparison, and optionally precision estimates, to a gate policy and write a pass, fail, or inconclusive decision with every requirement explained. Promotes nothing. |
76
+
77
+ Run `scaneval <command> --help` for required arguments. `corpus validate --snapshot-id`, `blinding check`, `run`, `dataset fetch`, and `benchmark run` can reach the network; contacts depend on the configured sources and scanners. Exit code `2` means the command could not be carried out, `1` means it ran and reports a negative result, and `0` means it ran and reports nothing wrong. None certifies that a security label is correct.
78
+
79
+ ## Scanners and visibility
80
+
81
+ The current adapters are `semgrep` with pinned local rules, `llm-harness` for an own-harness integration that drives the Fieldglass/SV-Agent engine directly, `deepsec` for the third-party scanner, and an initial `runsortie` integration that retains the evidence contract for full RunSortie orchestration: its Fieldglass engine, a primary agent's packet review, a separate challenger model, and RunSortie's own evidence commit. The production RunSortie route is currently fail-closed, as described below. `semgrep` (`--baseline-commit`) and `deepsec` (`process --diff`) also review a native PR request that names a base and a head commit in the scanner's workspace; [Current capabilities](docs/INITIAL_BUILD.md) says what each does with it. Scanner CLIs are installed separately. The optional `official-adapters` extra installs Semgrep; a reproducible comparison must also pin its version and rules. To build or review another execution integration, use the [scanner adapter builder skill](skills/scanner-adapter-builder/SKILL.md); it covers native workflow evidence and verification, not dataset import or corpus-label review.
82
+
83
+ The **ScanEval Observer SDK**, available in Python and TypeScript, records model calls, tool use, supplied context, and finding lifecycle events at instrumented boundaries. It is opt-in. Native collectors can import Claude Code and Codex records without claiming to see decisions the harness never exposed. Capture gaps remain explicit; traces cannot prove hidden reasoning or absence of memorization.
84
+
85
+ For the TypeScript SDK and harness driver:
86
+
87
+ ```bash
88
+ npm ci --prefix sdk/typescript
89
+ npm run build --prefix sdk/typescript
90
+ ```
91
+
92
+ On its default `local` runtime the `llm-harness` adapter needs a local harness checkout and the built SDK; its `oci_image` runtime uses the harness and observer SDK in its pinned image instead ([SV-Agent image runtime](docs/OPEN_CONTEXT.md#sv-agent-image-runtime)). The `deepsec` adapter needs an installed scanner workspace; it runs the scanner in a separate private workspace. The initial `runsortie` adapter parses the exact RunSortie `af8f240…`/`0.1.0` configuration and retains a deeply checked native evidence/completion implementation, but secure v1 has no runnable direct-agent boundary. Preparation records the requested routes as not runnable, and scan returns `unsupported` before checkout identity/content inspection or launch. Its deterministic fake and fabricated-agent conformance paths exercise the retained commit/tree, packet, prompt, journal, budget, snapshot, and reconciliation checks only; they are not live readiness ([details and limits](docs/INITIAL_BUILD.md#adapters)).
93
+
94
+ Guides: [Observer SDK](docs/OBSERVER_SDK.md), [native CLI collectors](docs/COLLECTORS.md), [context-coverage diagnostics](docs/DIAGNOSTICS.md).
95
+
96
+ Implementation review: [Inspect AI visibility and observability comparison](docs/INSPECT_OBSERVABILITY_COMPARISON.md).
97
+
98
+ ## Current limits
99
+
100
+ - Full-scan execution, native PR execution (a case pack declares a change set and states which targets and controls each PR review scores), case packs, source export, review, scoring, replay, and reports are implemented.
101
+ - Each run freezes its evaluation schedule (every assignment, pre-registered plan, and vulnerable/fixed pair) before it prepares an input. An input it cannot prepare is recorded with its skipped assignments, and the other inputs still run.
102
+ - The `metadata_blinded` profile applies reviewed token edits to documentation and display metadata. The `identity_reduced` profile adds hash-pinned identity-document/instruction removals and narrowly verified package URL leaf edits. An explicit strict policy validates answer coverage and records skipped transformations and residual cues; a profile name alone does not establish an experimental condition. Runtime code, dependency declarations, licenses, build/CI/security configuration, and source paths stay intact. Originals and transformation manifests remain evaluator-side. See [identity reduction](docs/IDENTITY_REDUCTION.md) for the reviewed workflow and limits.
103
+ - A saved SARIF 2.1.0 log imports offline into a bundle that review, score, and replay read; its execution report is recorded unverified ([SARIF import](docs/SARIF_IMPORT.md)). Other saved vendor formats have no importer.
104
+ - A system whose 2.1 run configuration selects the `oci` execution backend runs each scanner process in a locked-down Docker container from a digest-pinned image, with its network policy enforced (`unrestricted` is recorded as unenforced). `semgrep` can run under it, and so can the SV-Agent (`securevibes-agent`) harness through `llm-harness` with `config.runtime: "oci_image"`. That image runtime carries out full scans only, and only under the `oci` backend with the `public_research` policy; it is refused anywhere else. `deepsec`, `runsortie`, and `llm-harness` on `config.runtime: "local"` (a host checkout), are refused under `oci`. Under the `local` execution backend, systems run as the operator, unenforced. Implemented isolation does not show that a live-model scan has been validated or completed: at the default harness pin a scan still cannot reach a completed source-scan score, and no broad benchmark readiness is claimed. See [the threat model](docs/THREAT_MODEL.md) and [SV-Agent image runtime](docs/OPEN_CONTEXT.md#sv-agent-image-runtime).
105
+ - [Closed-book standard](docs/CLOSED_BOOK.md) preserves repository identity and classifies saved history, retrieval, network, and provider evidence as attested, declared-only, failed, or unavailable. A local policy declaration never attests isolation.
106
+ - The explicit `open_context` condition supplies bounded original ancestor history and controlled, recorded public retrieval under OCI. It measures assisted investigation; known-vulnerability retrieval may contribute to detection. History/capture coverage and provider visibility gaps stay visible, and its results remain separate from closed-book and identity-reduced observations ([guide and runnable fixture](docs/OPEN_CONTEXT.md)).
107
+ - `runsortie` has been validated only deterministically: by a stand-in that follows RunSortie's scan control flow, and by an opt-in run of the real pinned CLI with fabricated engine and agents. It has not run against a live model. Secure v1 has no runnable native direct-agent route: preparation records `runnable: false`, and invocation returns `unsupported` with an empty command before checkout identity/content inspection, credentials, probes, adapter-private state, or any RunSortie/agent process. Codex persists an API-key credential file readable by workspace tools; Claude 2.1.310 can fetch and apply remote managed helpers and additional filesystem roots; Cursor and Gemini likewise lack the externally attestable process/filesystem sandbox plus endpoint-specific egress control required here. The retained fake/conformance path tests native evidence and completion logic only and cannot be enabled by configuration. Unsupported assignments remain visible in evaluation accounting.
108
+ - Native PR review runs each scanner's own diff workflow over a neutral two-commit history of a declared change set: the harness's pr mode for `llm-harness`, `--baseline-commit` for `semgrep`, and `process --diff` for `deepsec`. An adapter without a PR mode is recorded as unsupported and stays in every denominator, and a full scan of the head never stands in for a PR review ([native PR review](docs/INITIAL_BUILD.md#native-pr-review)).
109
+ - Corpus aggregation and paired comparison read saved, frozen run directories ([aggregation](docs/AGGREGATION.md)). They compute no reviewed precision and decide no promotion.
110
+ - Reviewed precision comes only from people reviewing a seeded probability sample of delivered claims ([precision guide](docs/PRECISION.md)). It is not a repository false-positive rate.
111
+ - A gate decision holds a saved comparison to a policy you write and says whether its requirements held ([gate guide](docs/GATE.md)). It promotes nothing: the workflow that owns the harness decides.
112
+ - Fifty CVEs are selected in the [diverse corpus](corpus/diverse/README.md), including GitLab, Kubernetes, Airflow, Langflow, LangChain and Twenty. The [Astra-authored review skill](skills/cve-corpus-review/SKILL.md) supports machine review without a human gate; shared deployment context, claim-specific runtime validation and scanner preflight remain separate work. Java and Ruby are accepted by the corpus contract, but the current adapters still record them as unsupported. No representative benchmark or scanner comparison is claimed.
113
+ - External [dataset tracks](corpus/benchmarks/README.md) provide 469 PR cases and 223 additional OpenSSF CVE cases. Their publisher labels remain separate from the curated corpus. Dataset benchmark runs use the local execution backend; scoring measures reference coverage and named fixed controls, not true precision or an official upstream leaderboard score. Missing or uncertain semantic judgments remain explicit.
114
+
115
+ [Current capabilities](docs/INITIAL_BUILD.md) describes the implementation. [Design decisions](docs/DESIGN_DECISIONS.md) and [evaluation math](docs/EVALUATION_MATH.md) describe the broader contract and planned work.
116
+
117
+ ## Development
118
+
119
+ ```bash
120
+ python -m pytest -q
121
+ npm test --prefix sdk/typescript
122
+ ```
123
+
124
+ Tests use local fixtures and mock model runners. They do not launch paid model evaluations. CI checks Python 3.11, 3.13, and 3.14, the TypeScript SDK, and demo/replay from an installed wheel.
125
+
126
+ | Path | Contents |
127
+ |---|---|
128
+ | `src/scaneval/` | CLI, corpus, runner, evaluator, adapters, collectors, and Python Observer |
129
+ | `src/scaneval/schemas/` | Versioned evaluation contracts |
130
+ | `sdk/typescript/` | TypeScript Observer SDK |
131
+ | `schema/v2/` | Shared trace contract and conformance fixtures |
132
+ | `corpus/diverse/` | 50 selected CVEs, sourced severity distribution, pinned sources and machine review |
133
+ | `scripts/sanitize_native_trace.py` | Scrub native records for collector fixtures |
134
+ | `tests/` | Contract, scoring, runner, adapter, Observer, and collector tests |
135
+ | `docs/` | Public design and usage guides |
136
+
137
+ Generated runs belong under ignored `results/`; source caches belong under ignored `.repos/`. Do not commit scanner outputs, private findings, credentials, or content traces.
138
+
139
+ ## License
140
+
141
+ [MIT](LICENSE). Source snapshots and external scanners retain their own licenses.
142
+
143
+ ### Model cutoffs and recent CVE research
144
+
145
+ Inspect sourced provider cutoffs and check reviewed public-evidence chronology with
146
+ `scaneval model-cutoffs list` and `scaneval model-cutoffs check`. The read-only
147
+ helper preserves unknown dates and routes, distinguishes training from knowledge
148
+ cutoffs, and reports the 2 Low / 3 Medium / 3 High / 2 Critical research target.
149
+ See [model cutoffs](docs/MODEL_CUTOFFS.md) for usage, evidence limits, and maintenance.