gisel-ab 0.9.0__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 (223) hide show
  1. gisel_ab-0.9.0/.editorconfig +21 -0
  2. gisel_ab-0.9.0/CHANGELOG.md +77 -0
  3. gisel_ab-0.9.0/CONTRACTS.md +244 -0
  4. gisel_ab-0.9.0/CONTRIBUTING.md +67 -0
  5. gisel_ab-0.9.0/EVIDENCE.json +2828 -0
  6. gisel_ab-0.9.0/MANIFEST.in +14 -0
  7. gisel_ab-0.9.0/PKG-INFO +349 -0
  8. gisel_ab-0.9.0/README.md +336 -0
  9. gisel_ab-0.9.0/RELEASE.json +80 -0
  10. gisel_ab-0.9.0/SCOPE.md +164 -0
  11. gisel_ab-0.9.0/VERIFICATION.json +1523 -0
  12. gisel_ab-0.9.0/docs/ADOPT.md +117 -0
  13. gisel_ab-0.9.0/docs/BACKLOG.md +24 -0
  14. gisel_ab-0.9.0/docs/CLOSURE.md +180 -0
  15. gisel_ab-0.9.0/docs/EVIDENCE-U.md +425 -0
  16. gisel_ab-0.9.0/docs/EVIDENCE-W0.md +124 -0
  17. gisel_ab-0.9.0/docs/EVIDENCE-WP2.md +150 -0
  18. gisel_ab-0.9.0/docs/EVIDENCE-WP4-G-negative-control.md +93 -0
  19. gisel_ab-0.9.0/docs/EVIDENCE-WP4-predicate-negative.md +91 -0
  20. gisel_ab-0.9.0/docs/EVIDENCE-domain.md +413 -0
  21. gisel_ab-0.9.0/docs/EVIDENCE-riscv.md +165 -0
  22. gisel_ab-0.9.0/docs/GAPS.md +128 -0
  23. gisel_ab-0.9.0/docs/OFFICIAL-BASE.md +56 -0
  24. gisel_ab-0.9.0/docs/QUICKSTART-with-llvm.md +122 -0
  25. gisel_ab-0.9.0/docs/README.md +43 -0
  26. gisel_ab-0.9.0/docs/REPLAY-FROZEN.md +65 -0
  27. gisel_ab-0.9.0/docs/REPORT-ab.md +801 -0
  28. gisel_ab-0.9.0/docs/REPORT-mir.md +604 -0
  29. gisel_ab-0.9.0/docs/REQUIREMENTS-ab.md +222 -0
  30. gisel_ab-0.9.0/docs/TUTORIAL-m68k.md +171 -0
  31. gisel_ab-0.9.0/evidence.schema.json +103 -0
  32. gisel_ab-0.9.0/pyproject.toml +47 -0
  33. gisel_ab-0.9.0/scripts/adopt-check.sh +18 -0
  34. gisel_ab-0.9.0/scripts/check-pin.sh +126 -0
  35. gisel_ab-0.9.0/scripts/domain/run-aarch64-domain.sh +184 -0
  36. gisel_ab-0.9.0/scripts/domain/run-domain.sh +213 -0
  37. gisel_ab-0.9.0/scripts/domain/run-riscv-domain.sh +156 -0
  38. gisel_ab-0.9.0/scripts/domain/run-x86-domain.sh +101 -0
  39. gisel_ab-0.9.0/scripts/e2e/run-aarch64-end-to-end.sh +3 -0
  40. gisel_ab-0.9.0/scripts/e2e/run-arm-end-to-end.sh +3 -0
  41. gisel_ab-0.9.0/scripts/e2e/run-e2e.sh +76 -0
  42. gisel_ab-0.9.0/scripts/e2e/run-m68k-end-to-end.sh +3 -0
  43. gisel_ab-0.9.0/scripts/e2e/run-mips-end-to-end.sh +3 -0
  44. gisel_ab-0.9.0/scripts/e2e/run-ppc-end-to-end.sh +3 -0
  45. gisel_ab-0.9.0/scripts/e2e/run-riscv-end-to-end.sh +3 -0
  46. gisel_ab-0.9.0/scripts/e2e/run-spirv-end-to-end.sh +3 -0
  47. gisel_ab-0.9.0/scripts/e2e/run-u-end-to-end.sh +164 -0
  48. gisel_ab-0.9.0/scripts/e2e/run-wasm-end-to-end.sh +3 -0
  49. gisel_ab-0.9.0/scripts/e2e/run-x86-end-to-end.sh +3 -0
  50. gisel_ab-0.9.0/scripts/freeze-oracle.sh +54 -0
  51. gisel_ab-0.9.0/scripts/inc/build-inc.sh +11 -0
  52. gisel_ab-0.9.0/scripts/inc/restore-inc.sh +15 -0
  53. gisel_ab-0.9.0/scripts/inc/swap-inc.sh +48 -0
  54. gisel_ab-0.9.0/scripts/lib.sh +67 -0
  55. gisel_ab-0.9.0/scripts/negative/run-g-negative.sh +108 -0
  56. gisel_ab-0.9.0/scripts/negative/run-predicate-negative.sh +99 -0
  57. gisel_ab-0.9.0/scripts/run.sh +17 -0
  58. gisel_ab-0.9.0/scripts/runners/build-aarch64-runner.sh +76 -0
  59. gisel_ab-0.9.0/scripts/runners/build-arm-runner.sh +17 -0
  60. gisel_ab-0.9.0/scripts/runners/build-m68k-runner.sh +17 -0
  61. gisel_ab-0.9.0/scripts/runners/build-mips-runner.sh +17 -0
  62. gisel_ab-0.9.0/scripts/runners/build-ppc-runner.sh +17 -0
  63. gisel_ab-0.9.0/scripts/runners/build-query-runner.sh +78 -0
  64. gisel_ab-0.9.0/scripts/runners/build-riscv-runner.sh +75 -0
  65. gisel_ab-0.9.0/scripts/runners/build-runner.sh +66 -0
  66. gisel_ab-0.9.0/scripts/runners/build-spirv-runner.sh +17 -0
  67. gisel_ab-0.9.0/scripts/runners/build-wasm-runner.sh +17 -0
  68. gisel_ab-0.9.0/scripts/runners/build-x86-ctor-runner.sh +68 -0
  69. gisel_ab-0.9.0/scripts/snapshot.sh +39 -0
  70. gisel_ab-0.9.0/scripts/time-to-first-answer.sh +29 -0
  71. gisel_ab-0.9.0/scripts/verify-evidence.sh +23 -0
  72. gisel_ab-0.9.0/setup.cfg +4 -0
  73. gisel_ab-0.9.0/src/gisel_ab/__init__.py +120 -0
  74. gisel_ab-0.9.0/src/gisel_ab/__main__.py +8 -0
  75. gisel_ab-0.9.0/src/gisel_ab/baseline.py +145 -0
  76. gisel_ab-0.9.0/src/gisel_ab/bugreport.py +113 -0
  77. gisel_ab-0.9.0/src/gisel_ab/cli.py +150 -0
  78. gisel_ab-0.9.0/src/gisel_ab/cohort.py +704 -0
  79. gisel_ab-0.9.0/src/gisel_ab/cpp/aarch64_generated_ctor.cpp +23 -0
  80. gisel_ab-0.9.0/src/gisel_ab/cpp/aarch64_query_runner.cpp +380 -0
  81. gisel_ab-0.9.0/src/gisel_ab/cpp/arm_generated_ctor.cpp +18 -0
  82. gisel_ab-0.9.0/src/gisel_ab/cpp/arm_query_runner.cpp +58 -0
  83. gisel_ab-0.9.0/src/gisel_ab/cpp/m68k_generated_ctor.cpp +21 -0
  84. gisel_ab-0.9.0/src/gisel_ab/cpp/m68k_query_runner.cpp +43 -0
  85. gisel_ab-0.9.0/src/gisel_ab/cpp/mips_generated_ctor.cpp +16 -0
  86. gisel_ab-0.9.0/src/gisel_ab/cpp/mips_query_runner.cpp +52 -0
  87. gisel_ab-0.9.0/src/gisel_ab/cpp/ppc_generated_ctor.cpp +16 -0
  88. gisel_ab-0.9.0/src/gisel_ab/cpp/ppc_query_runner.cpp +46 -0
  89. gisel_ab-0.9.0/src/gisel_ab/cpp/query-recovery.h +229 -0
  90. gisel_ab-0.9.0/src/gisel_ab/cpp/query_runner.cpp +419 -0
  91. gisel_ab-0.9.0/src/gisel_ab/cpp/query_runner_common.h +417 -0
  92. gisel_ab-0.9.0/src/gisel_ab/cpp/riscv_generated_ctor.cpp +25 -0
  93. gisel_ab-0.9.0/src/gisel_ab/cpp/riscv_query_runner.cpp +379 -0
  94. gisel_ab-0.9.0/src/gisel_ab/cpp/spirv_generated_ctor.cpp +24 -0
  95. gisel_ab-0.9.0/src/gisel_ab/cpp/spirv_query_runner.cpp +98 -0
  96. gisel_ab-0.9.0/src/gisel_ab/cpp/wasm_generated_ctor.cpp +17 -0
  97. gisel_ab-0.9.0/src/gisel_ab/cpp/wasm_query_runner.cpp +52 -0
  98. gisel_ab-0.9.0/src/gisel_ab/cpp/x86_generated_ctor.cpp +24 -0
  99. gisel_ab-0.9.0/src/gisel_ab/data/aarch64-contract.json +102 -0
  100. gisel_ab-0.9.0/src/gisel_ab/data/baseline-2026-11-12.json +1684 -0
  101. gisel_ab-0.9.0/src/gisel_ab/data/closure/aarch64-D.json +156 -0
  102. gisel_ab-0.9.0/src/gisel_ab/data/closure/aarch64-G.json +75 -0
  103. gisel_ab-0.9.0/src/gisel_ab/data/closure/arm-D.json +50 -0
  104. gisel_ab-0.9.0/src/gisel_ab/data/closure/arm-G.json +57 -0
  105. gisel_ab-0.9.0/src/gisel_ab/data/closure/m68k-D.json +46 -0
  106. gisel_ab-0.9.0/src/gisel_ab/data/closure/m68k-G.json +54 -0
  107. gisel_ab-0.9.0/src/gisel_ab/data/closure/mips-D.json +50 -0
  108. gisel_ab-0.9.0/src/gisel_ab/data/closure/mips-G.json +87 -0
  109. gisel_ab-0.9.0/src/gisel_ab/data/closure/ppc-D.json +49 -0
  110. gisel_ab-0.9.0/src/gisel_ab/data/closure/ppc-G.json +56 -0
  111. gisel_ab-0.9.0/src/gisel_ab/data/closure/riscv-D.json +59 -0
  112. gisel_ab-0.9.0/src/gisel_ab/data/closure/riscv-G.json +66 -0
  113. gisel_ab-0.9.0/src/gisel_ab/data/closure/spirv-D.json +58 -0
  114. gisel_ab-0.9.0/src/gisel_ab/data/closure/spirv-G.json +58 -0
  115. gisel_ab-0.9.0/src/gisel_ab/data/closure/wasm-D.json +56 -0
  116. gisel_ab-0.9.0/src/gisel_ab/data/closure/wasm-G.json +62 -0
  117. gisel_ab-0.9.0/src/gisel_ab/data/closure/x86-D.json +60 -0
  118. gisel_ab-0.9.0/src/gisel_ab/data/closure/x86-G.json +66 -0
  119. gisel_ab-0.9.0/src/gisel_ab/data/domain.json +139 -0
  120. gisel_ab-0.9.0/src/gisel_ab/data/mir-configs.json +444 -0
  121. gisel_ab-0.9.0/src/gisel_ab/data/mir-shapes.jsonc +1168 -0
  122. gisel_ab-0.9.0/src/gisel_ab/data/riscv-contract.json +102 -0
  123. gisel_ab-0.9.0/src/gisel_ab/data/suite/README.md +81 -0
  124. gisel_ab-0.9.0/src/gisel_ab/data/suite/aarch64/official.answers.jsonl +12559 -0
  125. gisel_ab-0.9.0/src/gisel_ab/data/suite/aarch64/queries.jsonl +12559 -0
  126. gisel_ab-0.9.0/src/gisel_ab/data/suite/aarch64/suite.json +43 -0
  127. gisel_ab-0.9.0/src/gisel_ab/data/suite/m68k/official.answers.jsonl +35 -0
  128. gisel_ab-0.9.0/src/gisel_ab/data/suite/m68k/queries.jsonl +35 -0
  129. gisel_ab-0.9.0/src/gisel_ab/data/suite/m68k/suite.json +24 -0
  130. gisel_ab-0.9.0/src/gisel_ab/data/suite/riscv/official.answers.jsonl +6086 -0
  131. gisel_ab-0.9.0/src/gisel_ab/data/suite/riscv/queries.jsonl +6086 -0
  132. gisel_ab-0.9.0/src/gisel_ab/data/suite/riscv/suite.json +41 -0
  133. gisel_ab-0.9.0/src/gisel_ab/data/suite/x86/official.answers.jsonl +3014 -0
  134. gisel_ab-0.9.0/src/gisel_ab/data/suite/x86/queries.jsonl +3014 -0
  135. gisel_ab-0.9.0/src/gisel_ab/data/suite/x86/suite.json +33 -0
  136. gisel_ab-0.9.0/src/gisel_ab/data/targets/aarch64.json +39 -0
  137. gisel_ab-0.9.0/src/gisel_ab/data/targets/arm.json +39 -0
  138. gisel_ab-0.9.0/src/gisel_ab/data/targets/m68k.json +39 -0
  139. gisel_ab-0.9.0/src/gisel_ab/data/targets/mips.json +39 -0
  140. gisel_ab-0.9.0/src/gisel_ab/data/targets/ppc.json +39 -0
  141. gisel_ab-0.9.0/src/gisel_ab/data/targets/riscv.json +39 -0
  142. gisel_ab-0.9.0/src/gisel_ab/data/targets/schema.json +266 -0
  143. gisel_ab-0.9.0/src/gisel_ab/data/targets/spirv.json +39 -0
  144. gisel_ab-0.9.0/src/gisel_ab/data/targets/wasm.json +39 -0
  145. gisel_ab-0.9.0/src/gisel_ab/data/targets/x86-ctor.json +39 -0
  146. gisel_ab-0.9.0/src/gisel_ab/data/targets/x86.json +39 -0
  147. gisel_ab-0.9.0/src/gisel_ab/data/x86-contract.json +93 -0
  148. gisel_ab-0.9.0/src/gisel_ab/doctor.py +320 -0
  149. gisel_ab-0.9.0/src/gisel_ab/domain_plan.py +130 -0
  150. gisel_ab-0.9.0/src/gisel_ab/evidence.py +892 -0
  151. gisel_ab-0.9.0/src/gisel_ab/l0/__init__.py +0 -0
  152. gisel_ab-0.9.0/src/gisel_ab/l0/attribute.py +286 -0
  153. gisel_ab-0.9.0/src/gisel_ab/l0/closure.py +255 -0
  154. gisel_ab-0.9.0/src/gisel_ab/l0/diff.py +388 -0
  155. gisel_ab-0.9.0/src/gisel_ab/l0/g_attribution.py +93 -0
  156. gisel_ab-0.9.0/src/gisel_ab/l0/inject_opcode.py +123 -0
  157. gisel_ab-0.9.0/src/gisel_ab/l0/inject_predicate.py +150 -0
  158. gisel_ab-0.9.0/src/gisel_ab/l0/queries.py +215 -0
  159. gisel_ab-0.9.0/src/gisel_ab/l0/run.py +688 -0
  160. gisel_ab-0.9.0/src/gisel_ab/l0/swap.py +257 -0
  161. gisel_ab-0.9.0/src/gisel_ab/l0/u_attribution.py +192 -0
  162. gisel_ab-0.9.0/src/gisel_ab/l3.py +271 -0
  163. gisel_ab-0.9.0/src/gisel_ab/mir/__init__.py +0 -0
  164. gisel_ab-0.9.0/src/gisel_ab/mir/config_check.py +144 -0
  165. gisel_ab-0.9.0/src/gisel_ab/mir/from_query.py +717 -0
  166. gisel_ab-0.9.0/src/gisel_ab/mir/libs.py +252 -0
  167. gisel_ab-0.9.0/src/gisel_ab/mir/replay.py +548 -0
  168. gisel_ab-0.9.0/src/gisel_ab/paths.py +151 -0
  169. gisel_ab-0.9.0/src/gisel_ab/refresh_counts.py +80 -0
  170. gisel_ab-0.9.0/src/gisel_ab/replay_frozen.py +154 -0
  171. gisel_ab-0.9.0/src/gisel_ab/setup.py +92 -0
  172. gisel_ab-0.9.0/src/gisel_ab/suite.py +390 -0
  173. gisel_ab-0.9.0/src/gisel_ab/targets.py +287 -0
  174. gisel_ab-0.9.0/src/gisel_ab/vertical.py +654 -0
  175. gisel_ab-0.9.0/src/gisel_ab.egg-info/PKG-INFO +349 -0
  176. gisel_ab-0.9.0/src/gisel_ab.egg-info/SOURCES.txt +221 -0
  177. gisel_ab-0.9.0/src/gisel_ab.egg-info/dependency_links.txt +1 -0
  178. gisel_ab-0.9.0/src/gisel_ab.egg-info/entry_points.txt +2 -0
  179. gisel_ab-0.9.0/src/gisel_ab.egg-info/requires.txt +1 -0
  180. gisel_ab-0.9.0/src/gisel_ab.egg-info/top_level.txt +1 -0
  181. gisel_ab-0.9.0/tests/README.md +29 -0
  182. gisel_ab-0.9.0/tests/conftest.py +57 -0
  183. gisel_ab-0.9.0/tests/fixtures/target-registry-pre-w2.json +283 -0
  184. gisel_ab-0.9.0/tests/test_ab.py +255 -0
  185. gisel_ab-0.9.0/tests/test_attribution.py +53 -0
  186. gisel_ab-0.9.0/tests/test_attribution_keys.py +56 -0
  187. gisel_ab-0.9.0/tests/test_bug_report.py +42 -0
  188. gisel_ab-0.9.0/tests/test_closure.py +140 -0
  189. gisel_ab-0.9.0/tests/test_cohort.py +292 -0
  190. gisel_ab-0.9.0/tests/test_config.py +123 -0
  191. gisel_ab-0.9.0/tests/test_diff.py +300 -0
  192. gisel_ab-0.9.0/tests/test_distribution.py +32 -0
  193. gisel_ab-0.9.0/tests/test_doctor.py +124 -0
  194. gisel_ab-0.9.0/tests/test_domain_contracts.py +126 -0
  195. gisel_ab-0.9.0/tests/test_evidence_fetch.py +129 -0
  196. gisel_ab-0.9.0/tests/test_evidence_snapshot.py +54 -0
  197. gisel_ab-0.9.0/tests/test_evidence_strict.py +266 -0
  198. gisel_ab-0.9.0/tests/test_import_report.py +52 -0
  199. gisel_ab-0.9.0/tests/test_inject_predicate.py +62 -0
  200. gisel_ab-0.9.0/tests/test_installed_layout.py +151 -0
  201. gisel_ab-0.9.0/tests/test_key_contract.py +62 -0
  202. gisel_ab-0.9.0/tests/test_l3.py +81 -0
  203. gisel_ab-0.9.0/tests/test_leg_provenance.py +41 -0
  204. gisel_ab-0.9.0/tests/test_mir_from_query.py +217 -0
  205. gisel_ab-0.9.0/tests/test_mir_libs.py +182 -0
  206. gisel_ab-0.9.0/tests/test_mir_replay.py +317 -0
  207. gisel_ab-0.9.0/tests/test_negative_rc.py +46 -0
  208. gisel_ab-0.9.0/tests/test_negative_scripts.py +116 -0
  209. gisel_ab-0.9.0/tests/test_paths.py +189 -0
  210. gisel_ab-0.9.0/tests/test_query_recovery.py +143 -0
  211. gisel_ab-0.9.0/tests/test_release_manifest.py +143 -0
  212. gisel_ab-0.9.0/tests/test_replay_frozen.py +46 -0
  213. gisel_ab-0.9.0/tests/test_riscv_vertical.py +122 -0
  214. gisel_ab-0.9.0/tests/test_run_e2e.py +66 -0
  215. gisel_ab-0.9.0/tests/test_run_queries.py +144 -0
  216. gisel_ab-0.9.0/tests/test_runner_protocol.py +67 -0
  217. gisel_ab-0.9.0/tests/test_suite.py +194 -0
  218. gisel_ab-0.9.0/tests/test_targets_schema.py +219 -0
  219. gisel_ab-0.9.0/tests/test_verification.py +94 -0
  220. gisel_ab-0.9.0/tests/test_verify.py +118 -0
  221. gisel_ab-0.9.0/tests/test_verify_evidence.py +193 -0
  222. gisel_ab-0.9.0/tests/test_version.py +53 -0
  223. gisel_ab-0.9.0/tests/test_vertical_config_check.py +73 -0
@@ -0,0 +1,21 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ trim_trailing_whitespace = true
8
+ indent_style = space
9
+ indent_size = 4
10
+
11
+ [*.{json,jsonl,jsonc}]
12
+ indent_size = 2
13
+
14
+ [*.{yml,yaml,sh}]
15
+ indent_size = 2
16
+
17
+ [Makefile]
18
+ indent_style = tab
19
+
20
+ [*.md]
21
+ trim_trailing_whitespace = false
@@ -0,0 +1,77 @@
1
+ # Changelog
2
+
3
+ This file records shape changes to the workbench, not results. Counts,
4
+ commits and gate outcomes live in `RELEASE.json` and `VERIFICATION.json`,
5
+ which are generated and must not be hand-edited.
6
+
7
+ ## Unreleased — usability (cohort r12)
8
+
9
+ - `gisel-ab setup --llvm DIR --build DIR [--evidence DIR]` records the paths in
10
+ `$XDG_CONFIG_HOME/gisel-ab/config.json` (or `~/.config/...`; `GISEL_AB_CONFIG`
11
+ moves it), so a shell no longer needs `export AB_TREE=... AB_BUILD=...`.
12
+ Resolution is unchanged at the bottom: flag > environment > config > sibling.
13
+ - `setup` writes `llvm` and the resolver reads the same key; `run`, `mir` and
14
+ `verify` now accept an omitted `--tree`/`--build` and fall back to the
15
+ config (an explicit flag still wins, and keeps the old no-shape-check
16
+ behaviour). This closes the gap where `setup` only helped `vertical` and
17
+ `doctor`.
18
+ - `doctor` prints where each path came from (`(from AB_TREE)`, `(from
19
+ /path/config.json)`) and its fix line now names `gisel-ab setup` first.
20
+ Failures with nothing configured stay rc=2.
21
+ - `gisel-ab --help` groups verbs by what they need: without LLVM, with an LLVM
22
+ tree and build, with a git tree. `--version` reports 0.9.0.
23
+ - `doctor` gains `gisel-pin`: the installed gisel must match the cohort's
24
+ `RELEASE.json` version. A site-packages mismatch fails with the exact
25
+ `pip install gisel==...` line; a checkout mismatch only warns.
26
+ - `gisel graph` is unchanged in this cohort.
27
+ - `gisel-ab bug-report [--out FILE]` collects the three versions, the cohort
28
+ record, the doctor verdict and the last run's ledger line into one small
29
+ JSON file (no evidence tree), so an issue can carry the facts.
30
+ - Distribution: a composite action (`lint` + `cases` + `suite check`), a
31
+ pre-commit hook in gisel (`gisel-lint`), and
32
+ `scripts/time-to-first-answer.sh` (fresh venv -> installed tools -> an
33
+ answer, 300 s limit) wired into CI.
34
+ - The landing page and the eight-task cookbook live in gisel
35
+ (`docs/OVERVIEW-zh.md`, `docs/COOKBOOK-zh.md`, `docs/GLOSSARY-zh.md`);
36
+ this README links to them instead of duplicating the story.
37
+
38
+ ## Unreleased — productization (cohorts r8, r9)
39
+
40
+ - One entry point: `python3 ab.py <verb>` (or `gisel-ab` after
41
+ `pip install .`). The verb table is `doctor run mir verify diff l3 suite
42
+ vertical cohort evidence plan`; the old per-script entry points are gone.
43
+ - One package: every module moved under `src/gisel_ab/` (`l0/` for the
44
+ answer/diff layer, `mir/` for the MIR layer). Flat imports and the
45
+ `sys.path` shims that made them work are gone; `tests/conftest.py` keeps
46
+ the old names only as test aliases.
47
+ - Shell entry points moved under `scripts/` (`runners/`, `domain/`, `e2e/`,
48
+ `negative/`, `inc/`). `scripts/lib.sh` is the one place that defines the
49
+ roots and the negative-control exit-code contract.
50
+ - C++ query runners moved to `src/gisel_ab/cpp/`; the target registry, the
51
+ contracts, the domain table and the offline suite snapshots moved to
52
+ `src/gisel_ab/data/`.
53
+ - The frozen evidence tree moved from `oracle/` to `evidence/`. Contents and
54
+ hashes are unchanged; `EVIDENCE.json` is byte-identical.
55
+ - Packaging: `pyproject.toml` (src layout, `gisel-ab` console script, no
56
+ third-party dependencies) and `MANIFEST.in`. The wheel carries code, the
57
+ target registry, the suite snapshots and the C++ sources; the 102 MB
58
+ evidence tree is repository-only.
59
+ - CI gains a packaging job (install the wheel, run `--help` and the offline
60
+ suite, assert `evidence/` is absent) and a cohort check job.
61
+ - Installed state: `suite` resolves `gisel` and its `data/corpus`/`data/cases`
62
+ without a sibling checkout, `doctor` falls back to the pin the
63
+ `gisel-anchor` wheel ships, and `gisel-ab --version` exists. The packaging
64
+ smoke no longer sets `GISEL_SRC`, so the install-only path is what CI tests.
65
+ - `cohort check` treats a record that names an older cohort as "not written
66
+ yet" (rc=0, one line saying so) instead of drift. The record commit is a
67
+ child of the tag, so at the tag the manifest is already the new cohort while
68
+ `VERIFICATION.json` still names the previous one. `--worktree` keeps
69
+ failing in that state: a drift check needs a record for this cohort.
70
+ `r9` is the cohort that carries this fix and the refreshed anchor pin; its
71
+ evidence tree is byte-identical to `r8`.
72
+
73
+ ## Earlier
74
+
75
+ See the git history for r1–r7. Each cohort's gates and commits are in
76
+ `RELEASE.json`; the recorded verification of each tag is in
77
+ `VERIFICATION.json`.
@@ -0,0 +1,244 @@
1
+ # CONTRACTS:gisel-ab 的输入、输出与 runner 协议
2
+
3
+ 状态:WP0 草案。规范版本:query/answer JSONL = `cases-format v0.1`(下称
4
+ **schema v1**)。canonical 副本在 gisel 仓库 `spec/cases-format.md`。
5
+ 本项目不得单方面扩展字段。
6
+
7
+ ## 1 query JSONL
8
+
9
+ ```json
10
+ {"config":"x86-64-v3","name":"G_ADD","types":["s32"],"mem":null,"imms":[]}
11
+ ```
12
+
13
+ - 必填五字段:`config`、`name`、`types`、`mem`、`imms`。
14
+ - `types`:LLT 文本(`s32`、`i32`、`f16`、`v4s32`、`nxv4s32`、`p0:64`)。
15
+ - `mem`:`null` / `[mty, align]` / `[mty, align, ordering, failure]`;
16
+ 二元组读入时补 `("NotAtomic","NotAtomic")`。
17
+ - `imms`:整数数组,缺省 `[]`。
18
+ - 标注字段(`kind`、`ruleset`、`rule`、`reason`、`source`)不参与 key,必须忽略。
19
+ - 行序无语义;同一 key 重复且答案冲突是错误(rc=2)。
20
+
21
+ ## 2 key
22
+
23
+ ```text
24
+ (config, name, types, mem, imms)
25
+ ```
26
+
27
+ - 相等是**解析后的结构相等**,不是文本相等。
28
+ - `p0:*` 是通配,不等于 `p0:64`;runner 若把通配解析成具体宽度,必须同时改写
29
+ 查询文件,否则 key 对不上,只能算 `uncovered`。
30
+ - `mem` 归一成四元组后再比较。
31
+ - `types` 解析用 Core IR;`LLT_invalid` 不是类型,只作为答案哨兵。
32
+
33
+ ## 3 answer JSONL
34
+
35
+ 二选一,且必须原样回显 key 五字段(尤其 `types` 拼写):
36
+
37
+ ```json
38
+ {"config":"x86-64-v3","name":"G_ADD","types":["s32"],"mem":null,"imms":[],
39
+ "action":"Legal","type_idx":0,"new_type":"LLT_invalid"}
40
+ ```
41
+
42
+ ```json
43
+ {"config":"x86-64-v3","name":"G_ADD","types":["s32"],"mem":null,"imms":[],
44
+ "status":"unanswerable","reason":"asserted"}
45
+ ```
46
+
47
+ - `action`:`Legal`、`Lower`、`Libcall`、`Custom`、`Unsupported`、
48
+ `WidenScalar`、`NarrowScalar`、`FewerElements`、`MoreElements`、
49
+ `ClampScalar`、`ClampMaxNumElements`、`Scalarize`、`Unmerge` 等。
50
+ - `type_idx`:被改写的 slot 下标;无改写为 `0`。
51
+ - `new_type`:改写后的 LLT;无新类型写哨兵 `"LLT_invalid"`。
52
+ - `status:"unanswerable"`:双方都拒绝回答;不计入 `agree`,也不算通过。
53
+ - 断言(SIGABRT)由 runner 自己转成
54
+ `status:"unanswerable", reason:"asserted"`:runner 在 `getAction()` 外包了
55
+ `sigsetjmp` 恢复点,进程内继续答下一题。真正的崩溃(SIGSEGV)仍由
56
+ `run-queries.py` 重启并标记,已答行保留。
57
+
58
+ ## 4 runner 协议
59
+
60
+ ```sh
61
+ RUNNER --queries QUERIES.jsonl
62
+ ```
63
+
64
+ - 答案写 stdout,一行一个 JSON 对象,逐行 flush(崩溃前的答案必须保留)。
65
+ - 进度/诊断写 stderr(`answered N queries`)。
66
+ - 坏输入、未知 opcode、坏 LLT:exit 2,不产生半行 JSON。
67
+ - `run-queries.py`:0 = 每条查询都有答案或信号型 `unanswerable`;2 = runner
68
+ 以非断言信号退出(缺库、用法错、构建坏)。exit 2 时仍写答案文件和
69
+ `--report`,第一条未答查询标 `runner-error`,报告带 `failed_at`/`error`。
70
+ “坏输入但 rc=0 且没有产物”不再是可能的状态。
71
+ - runner 必须是纯函数:同一查询、同一二进制、同一配置,答案相同。
72
+ - 构建元数据(二进制 sha256、target、config、inc sha256、pin commit)记录在
73
+ run state 里,作为 `EVIDENCE.json` 的输入。
74
+
75
+ ## 5 diff 协议
76
+
77
+ ```sh
78
+ diff.py REF.jsonl OURS.jsonl [--queries QUERIES.jsonl] [--json]
79
+ [--compare action|full] [--allow-ref-asserts N]
80
+ [--expect-unanswerable N] [--details N]
81
+ ```
82
+
83
+ `--queries` 是题面分母:两侧答案的 key 集必须与它完全相等。没有这个参数时
84
+ 只能比较两侧的交集,两份被同样截断的答案会显示 `agree=N, disagree=0`;
85
+ 所有生产调用点都必须传。
86
+
87
+ 退出码:0 = 同 key 集且同答案;1 = 有差异、缺 key、`missing_in_both>0` 或
88
+ `unexpected>0`;2 = 坏行/重复 key 冲突/题面读不了。
89
+
90
+ 判定字段(JSON 报告):
91
+
92
+ | 字段 | 含义 |
93
+ |---|---|
94
+ | `ref` / `ours` | 两侧答案行数 |
95
+ | `matched` | 两侧都有的 key 数 |
96
+ | `agree` | 答案相同(含相同 `unanswerable`) |
97
+ | `unanswerable` | 两侧都 `unanswerable` 且理由相同 |
98
+ | `disagree` | 答案不同 |
99
+ | `missing_ref` / `missing_ours` | 单侧缺失的 key |
100
+ | `query_count` | `--queries` 的 key 数(未传为 null) |
101
+ | `missing_in_both` | 题面有、两侧答案都没有的 key 数(截断探测器) |
102
+ | `unexpected` | 答案有、题面没有的 key 数(越界探测器) |
103
+ | `ref_asserted` | 官方侧断言、我方有答案;只有显式 `--allow-ref-asserts` 才计为已知类 |
104
+ | `ref_asserted_by_site` | 上面这批的 `file:line`(fatal 消息则记消息)分布 |
105
+ | `ref_asserted_by_opcode` | 同一批按 opcode 的分布 |
106
+
107
+ 归因分类固定为:`status` → `action` → `type_idx` → `new_type`(最粗优先)。
108
+
109
+ `--allow-ref-asserts` 接受三种形式:`N` 钉总数;`site=count,...` 钉每个站点;
110
+ `@file.json` 从 JSON 对象读站点表。钉站点是默认建议:总数不变、站点重排
111
+ (一个旧断言消失、一个新断言顶上)在只钉总数时看不出来。
112
+
113
+ ## 6 负控
114
+
115
+ 至少两类:
116
+
117
+ 1. 注入错动作(把某条规则的 action 改掉);
118
+ 2. 注入错变异(改 `new_type` 选择)。
119
+
120
+ 负控必须使 `diff` rc=1 且 `disagree>0`;抓不到则 gate 失败,不允许冻结。
121
+ `EVIDENCE.json` 里负控的 `expect.disagree` 是精确值,不是下限;
122
+ `by_ruleset` 必须非空,且只能落在注入的 ruleset 上。
123
+
124
+ 统一退出码(`env.sh:classify_negative_rc`):
125
+
126
+ | rc | 含义 | 包装脚本返回 |
127
+ |---|---|---|
128
+ | 0 | diff 仍一致,注入没被观察到(blind) | 1 |
129
+ | 1 | 被抓到,且归因落在被注入的 ruleset | 0 |
130
+ | 2 | 输入/基础设施错(文件坏、构建挂、没有 diff.json) | 2 |
131
+ | 其他 | 一律按输入错处理,不算“抓到” | 2 |
132
+
133
+ 负控只会把 rc=1 当成功;崩溃、缺文件、runner 非断言退出都不会伪装成证据。
134
+
135
+ ## 7 版本演进
136
+
137
+ - schema v1 的改动先改 gisel `spec/cases-format.md` 并升版本。
138
+ - key 五元组是破坏性契约:三个项目同一 release 对齐。
139
+ - ab 的 key 实现必须有契约测试:固定 fixture 下与 `gisel.answers.key` 逐 key 相等。
140
+
141
+ ## 8 MIR/llc 报告(`mir-report.json`)
142
+
143
+ L1/L2 的产物,字段固定:
144
+
145
+ ```json
146
+ {"schema": 1, "layer": "upstream", "generated_at": "...",
147
+ "llc": "...", "llc_sha256": "...",
148
+ "expect": {"timeouts": null, "unsupported": null},
149
+ "unaccounted": [],
150
+ "totals": {"runs": 0, "same": 0, "both_abort": 0, "diff": 0,
151
+ "timeout": 0, "unsupported_run": 0},
152
+ "targets": {"x86": {"files": 0, "runs": 0, "same": 0, "both_abort": 0,
153
+ "diff": 0, "timeout": 0, "unsupported_run": 0}},
154
+ "inputs": {"official_libs": {"x86": "sha256"}, "ours_libs": {"x86": "sha256"}},
155
+ "files": [{"target": "x86", "path": "...", "runs": [
156
+ {"run": "llc ...", "status": "same", "official_rc": 0,
157
+ "ours_rc": 0, "detail": null}]}]}
158
+ ```
159
+
160
+ 恒等式(测试必须锁):
161
+
162
+ ```text
163
+ runs == same + both_abort + diff + timeout + unsupported_run
164
+ targets[*].runs 之和 == totals.runs
165
+ ```
166
+
167
+ - `same`:两侧 rc=0 且 stdout/stderr 相同。
168
+ - `both_abort`:两侧 rc!=0 且 stdout/stderr 相同;一致,但单独计数。
169
+ - `diff`:任何一侧的输出或 rc 不同。
170
+ - `timeout`:任一侧超过 `--timeout`。
171
+ - `unsupported_run`:RUN 行不是可重放的 `llc` 调用(例如 `FileCheck` 单独行)。
172
+
173
+ `timeout` 和 `unsupported_run` 是**没有被比较**的输入,不是“一致”。默认两者
174
+ 非零就是 rc=1;只有 `--expect-timeouts N` / `--expect-unsupported N` 显式钉住
175
+ 同一个数字才允许继续。新增一个 timeout 因此是回归,不是分母变大。`unaccounted`
176
+ 列出没钉住的桶,`expect` 记录这次的钉值。
177
+
178
+ 退出码:0 = `diff == 0`、`unaccounted == []` 且负控未触发;
179
+ 1 = 有 `diff`、单边 abort、未钉住的 timeout/unsupported、或负控没抓到;
180
+ 2 = 输入/参数/库错误。
181
+
182
+ ## 9 MIR 形状表(`data/mir-shapes.jsonc`)
183
+
184
+ 这是 `ab` 的产品数据,不是脚本里的临时 dict。
185
+
186
+ - `schema`:1。
187
+ - 每条 entry 必须带 `source`,指向 `GenericOpcodes.td`、MIR 语法文档或上游测试;
188
+ 没有 `source` 的条目在加载时拒绝(同 `gisel/contract.py` 的规矩)。
189
+ - 条目只描述“如何把一条查询写成合法 MIR”,不描述合法性答案。
190
+ - 不进入 gisel wheel,不属于 `.gisel` 语法,不改变四个出口。
191
+
192
+
193
+ ## 10 证据 manifest(`EVIDENCE.json` / `evidence.schema.json`)
194
+
195
+ `evidence.py verify` 是执行器,`evidence.schema.json` 是契约。每条 entry 必须
196
+ 带 `kind`,校验规则按 kind 分开:
197
+
198
+ | kind | 必须的产物 | 关键检查 |
199
+ |---|---|---|
200
+ | `answers` | `diff.json`(+ 答案文件) | 记录值、`answered_equal = agree - unanswerable`、`missing_in_both=unexpected=0` |
201
+ | `neg` | `diff.json`、`attribution.json` | `disagree` 精确相等;`by_ruleset` 非空且只含注入项 |
202
+ | `summary` | `summary.json` | 每配置聚合值与 `assert_sites` |
203
+ | `mir` | `mir-report.json` | bucket 恒等式、每 target、llc sha、恢复基线 |
204
+ | `lit` | 两轮 per-test JSONL | 重新计算状态,不信 `identical` |
205
+ | `closure` | `src/gisel_ab/data/closure/<target>-<seed>.json` | `ok`、`stuck=0`、`disagree=[]`、`ours_only=0` |
206
+ | `adopt` | gisel 的 `<t>.inc` + `docs/ADOPT.md` | inc sha、分支/commit/lib sha 在文档里 |
207
+
208
+ `verify-evidence.sh [DIRECTION]` 只做转发;`VERIFY_FROZEN=1` 时只读
209
+ `evidence/` 和 `src/gisel_ab/data/closure/`,并显式打印
210
+ `SKIP official_build frozen mode verifies artifacts, not the build`;
211
+ 汇总行另报 `N check(s) skipped`。SKIP 不是 PASS:冻结模式只证明产物字节,
212
+ 不证明产生它们的构建身份。非 frozen 模式缺构建目录或库哈希不符都是失败。
213
+
214
+ `adopt-check.sh` 会 `git fetch --depth=1` 三个采用分支,比较分支内 `.inc` 的
215
+ sha 与 gisel 产物;这是唯一需要网络的证据检查。
216
+
217
+ ## 11 Cohort 记录(`VERIFICATION.json`)
218
+
219
+ `RELEASE.json` 是可生成的清单:它只写提交、产物 SHA 和 gate 命令,且在
220
+ manifest commit 之后冻结。`VERIFICATION.json` 是它的子提交,写“这些门在
221
+ tag 上跑过没有”。
222
+
223
+ 必填字段:
224
+
225
+ | 字段 | 含义 |
226
+ |---|---|
227
+ | `schema` | 2 |
228
+ | `cohort` / `tag` | 与 `RELEASE.json.cohort` 相同,不带 `v` 前缀 |
229
+ | `manifest_commit` | 最后一次修改 `RELEASE.json` 的提交 |
230
+ | `commits` | tag 指向的三仓提交;`commits.ab == manifest_commit` |
231
+ | `gate_commits` | gate 实际运行的提交;当前与 `commits` 相同 |
232
+ | `gates[]` | `name` / `manifest_command` / `repo` / `command` / `rc` / `evidence` / `duration_s` / `inputs` 的 blob 映射 / `fingerprint` |
233
+ | `online_gates[]` | 需要网络的门;`pass` / `skipped` / `unknown`,不许把 `unknown` 记成 `pass` |
234
+ | `ci` | 每个 workflow 的 run id 与 conclusion;`publish.runs` 必须为 0 |
235
+ | `history[]` | 被取代的旧记录;旧 schema 原样保留 |
236
+
237
+ 规则:
238
+
239
+ - `fingerprint` 是每个输入文件 git blob id 的有序拼接再 sha256;提交记录
240
+ 不改变它,`cohort.py check` 因此能在不重跑 gate 的情况下报 `STALE`。
241
+ - 记录提交是 tag 的子提交;`test_verification` 在 manifest commit 上 skip,
242
+ 在记录提交上运行。
243
+ - tag 不重写。CI 红在 harness 自身时,修一个子提交,把绿 run 记进 `ci`,
244
+ 并在 `ci_notes` 写明哪条红 run、为什么。
@@ -0,0 +1,67 @@
1
+ # Contributing
2
+
3
+ ## The four layers
4
+
5
+ | Layer | Lives in | Contract |
6
+ |---|---|---|
7
+ | Command surface | `ab.py`, `src/gisel_ab/cli.py` | verb names and `--help`; routing only |
8
+ | L0 (rules) | `src/gisel_ab/l0/`, `src/gisel_ab/data/targets/` | `getAction()` equality, `CONTRACTS.md` §3 |
9
+ | MIR/llc | `src/gisel_ab/mir/`, `src/gisel_ab/data/mir-*.json*` | real `.mir` through `llc` |
10
+ | Shell entry points | `scripts/` | exit codes below |
11
+
12
+ New behaviour goes in a verb or a script; do not add a second entry point at
13
+ the repository root. `ab.py` is the only `.py` allowed there.
14
+
15
+ ## Exit codes
16
+
17
+ Every command that can be scripted keeps the existing contract:
18
+
19
+ - `0` success / no difference
20
+ - `1` a real difference, a failed gate, or a caught negative control
21
+ - `2` input or infrastructure error (never evidence)
22
+
23
+ Negative controls distinguish three states through
24
+ `scripts/lib.sh:classify_negative_rc`: `0` blind, `1` caught, `2` input
25
+ error. Anything else is treated as an input error; a crash is not evidence.
26
+
27
+ ## Frozen files
28
+
29
+ Do not hand-edit, reformat or regenerate:
30
+
31
+ - `EVIDENCE.json`, `VERIFICATION.json` (except adding a new cohort record)
32
+ - `evidence/**`
33
+ - `src/gisel_ab/data/suite/**` (regenerate with `ab.py suite check`, and say
34
+ why in the commit)
35
+
36
+ `ab.py evidence verify --frozen` and `ab.py cohort check` are the checks that
37
+ notice. A structural move changes gate fingerprints: cut a new cohort
38
+ (`-rN+1`), record it, and keep the old gate spellings in `cohort.py GATES` so
39
+ the old tag still replays.
40
+
41
+ ## Run the suite
42
+
43
+ ```sh
44
+ python3 -m pytest -q tests
45
+ VERIFY_FROZEN=1 ./scripts/verify-evidence.sh
46
+ python3 ab.py suite check --all
47
+ python3 ab.py doctor # needs AB_TREE/AB_BUILD for a full pass
48
+ ```
49
+
50
+ The suite needs a sibling `gisel` checkout (`GISEL_SRC` overrides it) but no
51
+ LLVM build; the tests that need a build are skipped without one.
52
+
53
+ ## Commit shape
54
+
55
+ One behaviour change per commit, message `gisel-ab: <one thing>`. A move is
56
+ its own commit (`git mv` only, no content edits), so review can see that the
57
+ bytes did not change. Cohort commits are `ab: freeze the rN cohort`,
58
+ `ab: record the rN verification`, `ab: record the rN CI runs`.
59
+
60
+ ## Adding a target
61
+
62
+ 1. Add `src/gisel_ab/data/targets/<name>.json` (schema in the same folder).
63
+ 2. Add a query runner under `src/gisel_ab/cpp/` and, if the target is not
64
+ covered by the generic runner, a `scripts/runners/build-<name>-runner.sh`.
65
+ 3. `ab.py refresh-counts --check` must agree; then run the e2e wrapper under
66
+ `scripts/e2e/`.
67
+ 4. Record the evidence, and only then add the target to a cohort.