aihr 0.2.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 (213) hide show
  1. aihr-0.2.0/LICENSE +21 -0
  2. aihr-0.2.0/PKG-INFO +299 -0
  3. aihr-0.2.0/README.md +261 -0
  4. aihr-0.2.0/aihr.egg-info/PKG-INFO +299 -0
  5. aihr-0.2.0/aihr.egg-info/SOURCES.txt +211 -0
  6. aihr-0.2.0/aihr.egg-info/dependency_links.txt +1 -0
  7. aihr-0.2.0/aihr.egg-info/entry_points.txt +2 -0
  8. aihr-0.2.0/aihr.egg-info/requires.txt +18 -0
  9. aihr-0.2.0/aihr.egg-info/top_level.txt +1 -0
  10. aihr-0.2.0/configs/deployable.yaml +26 -0
  11. aihr-0.2.0/configs/fleet.yaml +56 -0
  12. aihr-0.2.0/configs/hr.toml.example +26 -0
  13. aihr-0.2.0/configs/knowledge.yaml +824 -0
  14. aihr-0.2.0/configs/models.yaml +81 -0
  15. aihr-0.2.0/configs/seats.yaml +206 -0
  16. aihr-0.2.0/configs/thresholds.yaml +78 -0
  17. aihr-0.2.0/hr/__init__.py +3 -0
  18. aihr-0.2.0/hr/__main__.py +5 -0
  19. aihr-0.2.0/hr/adapters/__init__.py +127 -0
  20. aihr-0.2.0/hr/adapters/anthropic_compat.py +307 -0
  21. aihr-0.2.0/hr/adapters/anthropic_messages.py +43 -0
  22. aihr-0.2.0/hr/adapters/anthropic_stream.py +162 -0
  23. aihr-0.2.0/hr/adapters/base.py +115 -0
  24. aihr-0.2.0/hr/adapters/fleet.py +86 -0
  25. aihr-0.2.0/hr/adapters/openai_compat.py +253 -0
  26. aihr-0.2.0/hr/adapters/openai_endpoint.py +126 -0
  27. aihr-0.2.0/hr/adapters/openai_protocol.py +184 -0
  28. aihr-0.2.0/hr/apply.py +220 -0
  29. aihr-0.2.0/hr/assign/__init__.py +6 -0
  30. aihr-0.2.0/hr/assign/ranker.py +204 -0
  31. aihr-0.2.0/hr/bank_selection.py +253 -0
  32. aihr-0.2.0/hr/bank_versions.py +114 -0
  33. aihr-0.2.0/hr/bench/__init__.py +29 -0
  34. aihr-0.2.0/hr/bench/engine.py +295 -0
  35. aihr-0.2.0/hr/bench/engine_interactive.py +167 -0
  36. aihr-0.2.0/hr/bench/engine_results.py +58 -0
  37. aihr-0.2.0/hr/bench/engine_runners.py +142 -0
  38. aihr-0.2.0/hr/bench/engine_storage.py +134 -0
  39. aihr-0.2.0/hr/bench/livebench.py +163 -0
  40. aihr-0.2.0/hr/bench/manifest.py +57 -0
  41. aihr-0.2.0/hr/bench/prompt_image.py +47 -0
  42. aihr-0.2.0/hr/bench/prompts.py +301 -0
  43. aihr-0.2.0/hr/bench/scorer_attention.py +135 -0
  44. aihr-0.2.0/hr/bench/scorer_code.py +204 -0
  45. aihr-0.2.0/hr/bench/scorer_instruction.py +266 -0
  46. aihr-0.2.0/hr/bench/scorer_reasoning.py +255 -0
  47. aihr-0.2.0/hr/bench/scorer_runtime.py +76 -0
  48. aihr-0.2.0/hr/bench/scorer_shared.py +107 -0
  49. aihr-0.2.0/hr/bench/scorers.py +14 -0
  50. aihr-0.2.0/hr/bench/stress_prompts.py +94 -0
  51. aihr-0.2.0/hr/bench/truths.py +281 -0
  52. aihr-0.2.0/hr/benchmark_banks.py +300 -0
  53. aihr-0.2.0/hr/calibrate.py +14 -0
  54. aihr-0.2.0/hr/calibration_cli.py +177 -0
  55. aihr-0.2.0/hr/calibration_items.py +237 -0
  56. aihr-0.2.0/hr/calibration_models.py +157 -0
  57. aihr-0.2.0/hr/calibration_persistence.py +129 -0
  58. aihr-0.2.0/hr/calibration_runner.py +270 -0
  59. aihr-0.2.0/hr/cli.py +69 -0
  60. aihr-0.2.0/hr/cli_app.py +65 -0
  61. aihr-0.2.0/hr/cli_apply.py +170 -0
  62. aihr-0.2.0/hr/cli_inventory.py +221 -0
  63. aihr-0.2.0/hr/cli_knowledge.py +149 -0
  64. aihr-0.2.0/hr/cli_report_base.py +165 -0
  65. aihr-0.2.0/hr/cli_report_commands.py +125 -0
  66. aihr-0.2.0/hr/cli_report_verdict.py +165 -0
  67. aihr-0.2.0/hr/cli_selection.py +85 -0
  68. aihr-0.2.0/hr/config.py +305 -0
  69. aihr-0.2.0/hr/config_resources.py +73 -0
  70. aihr-0.2.0/hr/db.py +176 -0
  71. aihr-0.2.0/hr/db_schema.py +249 -0
  72. aihr-0.2.0/hr/decision.py +256 -0
  73. aihr-0.2.0/hr/deployable.py +130 -0
  74. aihr-0.2.0/hr/deployment_manager.py +1222 -0
  75. aihr-0.2.0/hr/discover.py +192 -0
  76. aihr-0.2.0/hr/fleet.py +228 -0
  77. aihr-0.2.0/hr/fleet_policy.py +91 -0
  78. aihr-0.2.0/hr/graders/__init__.py +32 -0
  79. aihr-0.2.0/hr/graders/base.py +150 -0
  80. aihr-0.2.0/hr/graders/citation.py +152 -0
  81. aihr-0.2.0/hr/graders/constraint.py +240 -0
  82. aihr-0.2.0/hr/graders/constraint_dsl.py +138 -0
  83. aihr-0.2.0/hr/graders/exact_match.py +234 -0
  84. aihr-0.2.0/hr/graders/llm_judge.py +117 -0
  85. aihr-0.2.0/hr/graders/schema_valid.py +244 -0
  86. aihr-0.2.0/hr/graders/unit_test.py +140 -0
  87. aihr-0.2.0/hr/health.py +253 -0
  88. aihr-0.2.0/hr/health_metrics.py +143 -0
  89. aihr-0.2.0/hr/items/__init__.py +43 -0
  90. aihr-0.2.0/hr/items/loader.py +287 -0
  91. aihr-0.2.0/hr/items/payloads.py +189 -0
  92. aihr-0.2.0/hr/items/schema.py +225 -0
  93. aihr-0.2.0/hr/keyscan.py +264 -0
  94. aihr-0.2.0/hr/models.py +32 -0
  95. aihr-0.2.0/hr/opencfg.py +107 -0
  96. aihr-0.2.0/hr/plugin_safety.py +845 -0
  97. aihr-0.2.0/hr/publish.py +151 -0
  98. aihr-0.2.0/hr/recommend.py +804 -0
  99. aihr-0.2.0/hr/recommendation_constraints.py +318 -0
  100. aihr-0.2.0/hr/reference.py +39 -0
  101. aihr-0.2.0/hr/registry.py +96 -0
  102. aihr-0.2.0/hr/release_manifest.py +308 -0
  103. aihr-0.2.0/hr/research.py +38 -0
  104. aihr-0.2.0/hr/sandbox.py +98 -0
  105. aihr-0.2.0/hr/scheduler/__init__.py +15 -0
  106. aihr-0.2.0/hr/scheduler/taxonomy.py +258 -0
  107. aihr-0.2.0/hr/schema_migration.py +78 -0
  108. aihr-0.2.0/hr/scorer_calibration.py +764 -0
  109. aihr-0.2.0/hr/seats/__init__.py +20 -0
  110. aihr-0.2.0/hr/seats/health_gates.py +210 -0
  111. aihr-0.2.0/hr/seats/health_policy.py +104 -0
  112. aihr-0.2.0/hr/seats/rolespec.py +217 -0
  113. aihr-0.2.0/hr/seats/seed.py +194 -0
  114. aihr-0.2.0/hr/stage0.py +264 -0
  115. aihr-0.2.0/hr/stage0_call.py +155 -0
  116. aihr-0.2.0/hr/stage0_cli.py +184 -0
  117. aihr-0.2.0/hr/stage0_loop.py +125 -0
  118. aihr-0.2.0/hr/stage0_plan.py +89 -0
  119. aihr-0.2.0/hr/stage0_selection.py +251 -0
  120. aihr-0.2.0/hr/stage0_stats.py +201 -0
  121. aihr-0.2.0/hr/stage0_storage.py +344 -0
  122. aihr-0.2.0/hr/stage1.py +265 -0
  123. aihr-0.2.0/hr/stage1_cli.py +210 -0
  124. aihr-0.2.0/hr/stage1_loop.py +301 -0
  125. aihr-0.2.0/hr/stage1_plan.py +103 -0
  126. aihr-0.2.0/hr/stage1_resume.py +148 -0
  127. aihr-0.2.0/hr/stage1_selection.py +163 -0
  128. aihr-0.2.0/hr/stage1_state.py +157 -0
  129. aihr-0.2.0/hr/stage1_stats.py +71 -0
  130. aihr-0.2.0/hr/stats/__init__.py +10 -0
  131. aihr-0.2.0/hr/stats/bootstrap.py +131 -0
  132. aihr-0.2.0/hr/stats/empirical_bernstein.py +230 -0
  133. aihr-0.2.0/hr/stats/sequential.py +183 -0
  134. aihr-0.2.0/pyproject.toml +98 -0
  135. aihr-0.2.0/setup.cfg +4 -0
  136. aihr-0.2.0/tests/test_apply.py +139 -0
  137. aihr-0.2.0/tests/test_apply_contract.py +180 -0
  138. aihr-0.2.0/tests/test_apply_safety.py +287 -0
  139. aihr-0.2.0/tests/test_audit_config.py +172 -0
  140. aihr-0.2.0/tests/test_audit_inventory.py +138 -0
  141. aihr-0.2.0/tests/test_audit_paths.py +129 -0
  142. aihr-0.2.0/tests/test_audit_regressions.py +67 -0
  143. aihr-0.2.0/tests/test_benchmark_banks.py +578 -0
  144. aihr-0.2.0/tests/test_benchmark_scorers.py +320 -0
  145. aihr-0.2.0/tests/test_blend.py +87 -0
  146. aihr-0.2.0/tests/test_bootstrap.py +70 -0
  147. aihr-0.2.0/tests/test_calibrate.py +118 -0
  148. aihr-0.2.0/tests/test_calibrate_capabilities.py +35 -0
  149. aihr-0.2.0/tests/test_calibrate_items.py +391 -0
  150. aihr-0.2.0/tests/test_calibrate_persistence.py +198 -0
  151. aihr-0.2.0/tests/test_calibration_cli.py +235 -0
  152. aihr-0.2.0/tests/test_calibration_items_surface.py +209 -0
  153. aihr-0.2.0/tests/test_calibration_runner_surface.py +199 -0
  154. aihr-0.2.0/tests/test_capabilities.py +132 -0
  155. aihr-0.2.0/tests/test_cli.py +150 -0
  156. aihr-0.2.0/tests/test_cli_knowledge_surface.py +192 -0
  157. aihr-0.2.0/tests/test_cli_reports.py +204 -0
  158. aihr-0.2.0/tests/test_cli_verdict_status.py +177 -0
  159. aihr-0.2.0/tests/test_config.py +241 -0
  160. aihr-0.2.0/tests/test_db.py +256 -0
  161. aihr-0.2.0/tests/test_db_connect_surface.py +182 -0
  162. aihr-0.2.0/tests/test_db_contracts.py +611 -0
  163. aihr-0.2.0/tests/test_db_contracts_empty.py +100 -0
  164. aihr-0.2.0/tests/test_db_contracts_readers.py +487 -0
  165. aihr-0.2.0/tests/test_db_upgrade_path.py +306 -0
  166. aihr-0.2.0/tests/test_deployable.py +175 -0
  167. aihr-0.2.0/tests/test_deployment_manager.py +1508 -0
  168. aihr-0.2.0/tests/test_discover.py +128 -0
  169. aihr-0.2.0/tests/test_discover_auth_sources.py +164 -0
  170. aihr-0.2.0/tests/test_discover_inventory.py +174 -0
  171. aihr-0.2.0/tests/test_fleet.py +84 -0
  172. aihr-0.2.0/tests/test_fleet_config_sources.py +74 -0
  173. aihr-0.2.0/tests/test_fleet_policy.py +213 -0
  174. aihr-0.2.0/tests/test_gate_metrics.py +189 -0
  175. aihr-0.2.0/tests/test_graders_surface.py +223 -0
  176. aihr-0.2.0/tests/test_health.py +236 -0
  177. aihr-0.2.0/tests/test_health_gates.py +315 -0
  178. aihr-0.2.0/tests/test_keyscan.py +120 -0
  179. aihr-0.2.0/tests/test_plugin_safety.py +848 -0
  180. aihr-0.2.0/tests/test_publish.py +248 -0
  181. aihr-0.2.0/tests/test_ranker.py +258 -0
  182. aihr-0.2.0/tests/test_ranking_decisions.py +150 -0
  183. aihr-0.2.0/tests/test_recommend.py +782 -0
  184. aihr-0.2.0/tests/test_recommendation_constraints.py +250 -0
  185. aihr-0.2.0/tests/test_release_surface.py +493 -0
  186. aihr-0.2.0/tests/test_research_surface.py +55 -0
  187. aihr-0.2.0/tests/test_rolespec_surface.py +88 -0
  188. aihr-0.2.0/tests/test_sandbox.py +37 -0
  189. aihr-0.2.0/tests/test_scheduler_taxonomy_surface.py +133 -0
  190. aihr-0.2.0/tests/test_scorer_calibration.py +732 -0
  191. aihr-0.2.0/tests/test_scorer_governance.py +340 -0
  192. aihr-0.2.0/tests/test_scratch_db_fixture.py +193 -0
  193. aihr-0.2.0/tests/test_seats_seed.py +316 -0
  194. aihr-0.2.0/tests/test_sequential.py +132 -0
  195. aihr-0.2.0/tests/test_sequential_validity.py +680 -0
  196. aihr-0.2.0/tests/test_stage0.py +115 -0
  197. aihr-0.2.0/tests/test_stage0_call_unit.py +206 -0
  198. aihr-0.2.0/tests/test_stage0_cli_unit.py +212 -0
  199. aihr-0.2.0/tests/test_stage0_plan_unit.py +106 -0
  200. aihr-0.2.0/tests/test_stage0_selection_calls.py +218 -0
  201. aihr-0.2.0/tests/test_stage0_selection_unit.py +230 -0
  202. aihr-0.2.0/tests/test_stage0_stats_unit.py +232 -0
  203. aihr-0.2.0/tests/test_stage0_storage.py +199 -0
  204. aihr-0.2.0/tests/test_stage0_sweep.py +180 -0
  205. aihr-0.2.0/tests/test_stage1.py +166 -0
  206. aihr-0.2.0/tests/test_stage1_cli_surface.py +165 -0
  207. aihr-0.2.0/tests/test_stage1_config.py +64 -0
  208. aihr-0.2.0/tests/test_stage1_planning.py +192 -0
  209. aihr-0.2.0/tests/test_stage1_resume.py +252 -0
  210. aihr-0.2.0/tests/test_stage1_selection_surface.py +142 -0
  211. aihr-0.2.0/tests/test_stage1_stats_surface.py +102 -0
  212. aihr-0.2.0/tests/test_subsystems.py +268 -0
  213. aihr-0.2.0/tests/test_verdict_knobs.py +184 -0
aihr-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TachikomaGundam
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.
aihr-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,299 @@
1
+ Metadata-Version: 2.4
2
+ Name: aihr
3
+ Version: 0.2.0
4
+ Summary: HR Agent (人事) — model evaluation and role assignment for oh-my-openagent
5
+ Author: TachikomaGundam
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/TachikomaGundam/AIHR
8
+ Project-URL: Repository, https://github.com/TachikomaGundam/AIHR
9
+ Project-URL: Issues, https://github.com/TachikomaGundam/AIHR/issues
10
+ Keywords: llm,model-evaluation,benchmark,benchmarking,livebench,role-assignment,opencode
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: typer~=0.27
22
+ Requires-Dist: rich~=13.9
23
+ Requires-Dist: httpx~=0.28
24
+ Requires-Dist: pydantic~=2.13
25
+ Requires-Dist: psycopg2-binary~=2.9
26
+ Requires-Dist: numpy~=2.5
27
+ Requires-Dist: pyyaml~=6.0
28
+ Requires-Dist: requests~=2.32
29
+ Provides-Extra: test
30
+ Requires-Dist: basedpyright~=1.39; extra == "test"
31
+ Requires-Dist: pytest~=9.1; extra == "test"
32
+ Requires-Dist: pytest-cov~=7.1; extra == "test"
33
+ Requires-Dist: pytest-timeout~=2.4; extra == "test"
34
+ Requires-Dist: ruff~=0.16; extra == "test"
35
+ Provides-Extra: vision
36
+ Requires-Dist: pillow~=12.1; extra == "vision"
37
+ Dynamic: license-file
38
+
39
+ # HR: Agent Seat Matching and Capability Benchmarking
40
+
41
+ Unified harness that matches autonomous LLM coding agents to task-appropriate seats, runs capability benchmarks across model fleets, and emits deployment verdicts. One package, one database schema, and 13 CLI commands.
42
+
43
+ The English version is canonical. The Chinese version (`README.zh-CN.md`) is a faithful mirror. When the two diverge, the English text governs.
44
+
45
+ ## What HR Decides
46
+
47
+ HR is a decision-support plugin for assigning configured models to autonomous-agent seats. It does not claim that a model is universally "best". Its output is a bounded recommendation for a named seat or task, backed by a versioned item pool, the recorded model responses, health gates, and the policy in `configs/`.
48
+
49
+ The decision pipeline is:
50
+
51
+ 1. `hr discover` derives the candidate fleet from the live OpenCode configuration.
52
+ 2. `hr seed` registers seats, batteries, and item metadata in PostgreSQL.
53
+ 3. `hr calibrate` validates anchor-model difficulty bands against the item pool.
54
+ 4. `hr bench` or the Stage 0/Stage 1 sweep records scored measurements.
55
+ 5. `hr health`, `hr verdict`, and `hr recommend` apply capability, reliability, and seat gates.
56
+ 6. `hr apply` exports the accepted seat assignment to a FastDraw preset; it never changes a model assignment by itself unless explicitly requested.
57
+
58
+ ## Decision Statuses
59
+
60
+ Scores alone are not a safe decision contract. HR distinguishes these states:
61
+
62
+ | Status | Meaning | Allowed to rank or assign? |
63
+ |--------|---------|----------------------------|
64
+ | `pass` | All required items were measured and the configured rule passed. | Yes, subject to seat gates. |
65
+ | `fail` | All required items were measured and the configured rule failed. | No for that rule. |
66
+ | `inconclusive` | Samples are incomplete or an adapter/infrastructure failure occurred. | No; rerun or resume safely. |
67
+ | `invalid` | The configured item pool cannot support the requested rule. | No; repair the pool/configuration. |
68
+ | `not_applicable` | The model cannot perform the requested modality or tool protocol. | No for that capability; never coerce it to a zero-score capability failure. |
69
+
70
+ Calibration currently emits `pass`, `fail`, `inconclusive`, and `invalid`. Live benchmark and recommendation paths retain infrastructure incidents in the database and are being migrated to the same complete outcome contract. A token cap, a partial round, or a resumed run with missing measurements is evidence of uncertainty, not evidence that the model failed the task.
71
+
72
+ ## Methodology
73
+
74
+ ### Item pools and grading
75
+
76
+ `itemrepo/` is versioned test material. Every item has an item key, type, tier, payload, and grading specification. Batteries group items by capability, for example reasoning, factuality/hallucination, vision, `tool_a`, and `tool_b`. Graders are deterministic where possible: exact-match, schema, constraint, citation, and sandboxed unit-test graders. LLM judging is kept explicit because it introduces a second model and a second source of uncertainty.
77
+
78
+ Calibration uses anchor models and tier acceptance bands. Its purpose is not to select a production model. It detects a broken, missing, or difficulty-shifted item pool before that pool is used to decide seat assignments. A complete tier is required before a band can pass; malformed or missing evidence must not produce a vacuous pass.
79
+
80
+ ### Repeated measurement and separation
81
+
82
+ Stage 0 cheaply narrows the fleet. Stage 1 evaluates finalists against the full item banks. Each measurement is indexed by model, battery, round, item, and repetition so that repeated calls can be audited and resumed. Pairwise separation compares matched model/item observations; the item is the primary independent unit, and repetitions estimate gateway and generation variability.
83
+
84
+ Do not interpret a small point-score difference as a seat decision. A candidate should only displace another candidate when the relevant items are complete, the confidence/separation rule is met, and both candidates pass the seat's hard gates. The current implementation records pairwise bootstrap separation and sequential precision diagnostics. Planned hardening is documented in `docs/en/capability-prior.md`: per-model stopping, complete paired-round enforcement, and multiplicity-aware comparisons.
85
+
86
+ ### Health, constraints, and recommendation
87
+
88
+ Health is independent evidence, not a cosmetic penalty. It includes answer completion, self-consistency, tool reliability, and observed failures. A seat can impose required capabilities, context limits, and a health gate. A model without a required modality or one with insufficient evidence must be unassigned or reported as indeterminate rather than promoted by a fallback average.
89
+
90
+ Cost, latency, freshness, and uncertainty are part of the recommendation problem. `configs/models.yaml` supplies known price/capability facts; measurements supply observed behavior. Reference scores in `configs/knowledge.yaml` are priors, never replacements for a missing required live capability measurement.
91
+
92
+ ### Reproducibility and audit trail
93
+
94
+ The database stores sweeps, runs, measurements, infra incidents, separations, and calibration events. Preserve the item-pool hash, configuration revision, endpoint/model identity, timeout/retry policy, grader version, and random seed with every externally shared conclusion. Reports without that provenance are operational hints, not reproducible experiments.
95
+
96
+ ## Safety Rules
97
+
98
+ - The default `bash scripts/test.sh` and `--ci` modes explicitly remove inherited database credentials. They cannot silently use an ambient production DSN.
99
+ - `bash scripts/test.sh --with-db` accepts only an `hr_test_*` scratch database. It rejects names such as `wiki`.
100
+ - Generated artifacts resolve outside the repository by default. Tests seal `HOME`, OpenCode config, HR config, item repository, and output paths into temporary directories.
101
+ - A test session compares `git status --porcelain` before and after execution. Unexpected writes in the repository fail the suite.
102
+ - Production provider credentials belong in environment variables or local overlays, never in tracked YAML, `hr.toml`, test fixtures, or reports.
103
+
104
+ ## Install
105
+
106
+ ```bash
107
+ pip install .
108
+ ```
109
+
110
+ Source, editable, and wheel installs are supported. Packaged configuration resolves from the installation's `share/aihr` directory. Executable-code benchmarks fail closed unless Bubblewrap (`bwrap`) is installed; on Debian/Ubuntu use `sudo apt-get install bubblewrap`. If an older `hr-cli` or `hr-bench` package is already installed, remove it first:
111
+
112
+ ```bash
113
+ pip uninstall hr-cli hr-bench -y
114
+ pip install .
115
+ ```
116
+
117
+ ### Environment Variables
118
+
119
+ | Variable | Purpose | Default |
120
+ |----------|---------|---------|
121
+ | `HR_DSN` | Override the PostgreSQL connection string (preferred over `HR_DB_PASSWORD` + `db_*` fields) | unset |
122
+ | `HR_HOME` | Force an alternate config root (configs/, `hr.toml`, `itemrepo` are resolved from here) | repo root |
123
+ | `HR_COMPOSE_FILE` | Override the `docker compose` manifest that DB password resolution probes | unset |
124
+ | `HR_ITEMREPO` | Override the benchmark item repo directory | `HR_HOME/itemrepo` |
125
+ | `HR_OUTPUT_DIR` | Override the runtime output root for run artifacts | platform cache dir (see below) |
126
+
127
+ ### Output root (run artifacts)
128
+
129
+ Generated artifacts (bench exports, calibration reports, sweep dumps, …) NEVER land inside the repo tree. They resolve through `hr.config.output_root()`: `HR_OUTPUT_DIR` env var wins, otherwise the platform cache dir (`$XDG_CACHE_HOME/hr`, `~/Library/Caches/hr`, `%LOCALAPPDATA%/hr\Cache`), otherwise the system temp dir. CLI flags that name an explicit output path always win at the call site.
130
+
131
+ ### Configuration
132
+
133
+ Copy the example `hr.toml` if you need the DB / Wiki.js knobs:
134
+
135
+ ```bash
136
+ cp configs/hr.toml.example hr.toml
137
+ ```
138
+
139
+ There is no single "source of truth" file — configuration is split by concern across `configs/`, plus the runtime opencode config:
140
+
141
+ ### Local overlays (`configs/*.local.yaml`)
142
+
143
+ The tracked configs ship ZERO real deployment values (placeholder examples
144
+ where a value is machine-specific). A live machine's real values live in the
145
+ gitignored local overlays — `configs/seats.local.yaml`, `configs/fleet.local.yaml`,
146
+ `configs/deployable.local.yaml`, `configs/models.local.yaml` — which
147
+ `hr.config.load_yaml` deep-merges over the tracked files automatically:
148
+ **local wins per key; dicts merge recursively; lists are replaced, never
149
+ merged.** A missing overlay is normal (the tracked file is used as-is).
150
+
151
+ First-install: `cp configs/seats.yaml configs/seats.local.yaml`,
152
+ `cp configs/fleet.yaml configs/fleet.local.yaml`,
153
+ `cp configs/deployable.yaml configs/deployable.local.yaml` (and
154
+ `configs/models.yaml` → `models.local.yaml` if your gateway facts differ),
155
+ then fill in your real anchors, wire overrides, gateway URLs and
156
+ `extra_deployable` list. Never edit deployment values into the tracked
157
+ files — *any* `.local.yaml` is safe for real values, *nothing else* is.
158
+
159
+ The per-file split:
160
+
161
+ - `configs/thresholds.yaml` — numeric sweep and gate thresholds (stage0 budgets, half-widths, acceptance bands).
162
+ - `configs/models.yaml` — model pricing and the capability overlay (thinking/vision), keyed by bare model slug; unknown models get safe defaults.
163
+ - `configs/knowledge.yaml` — curated reference scores and qualitative research findings, keyed by bare model slug (unknown models are skipped).
164
+ - `configs/fleet.yaml` — OPTIONAL overrides for the dynamic fleet: `wire_overrides`, `scope_excludes`, and `gateway_urls` (base URLs for registry-only providers).
165
+ - `configs/seats.yaml` — seat definitions, per-seat `primary_capabilities`, and the stage-0 `calibration_anchors`.
166
+ - `configs/deployable.yaml` — `extra_deployable`: models served outside the opencode config (the only hand-maintained model list).
167
+ - `configs/hr.toml.example` — template for the root `hr.toml` (DB connection + optional Wiki.js publish target). Secrets are NEVER stored here: they come from the environment (`HR_DSN`, `HR_DB_PASSWORD`, provider keys).
168
+
169
+ The model fleet itself is not declared in this repo: it is derived at runtime from the opencode config (`opencode.jsonc` provider blocks) and merged with the `deployable.yaml` extras — see Universality below.
170
+
171
+ ## CLI Map
172
+
173
+ Thirteen commands, each targeting a specific concern. Legacy v1 commands (`evaluate`, `report`, `run_all`) were retired. `hr verdict` supersedes the retired evaluation path.
174
+
175
+ | Command | Purpose |
176
+ |---------|---------|
177
+ | `hr discover` | Enumerate providers/models from `opencode.jsonc` into `hr` (scope + auth presence) |
178
+ | `hr seed` | Initialize the schema and seed canonical seat definitions |
179
+ | `hr bench` | Run the live capability benchmarks and record `hr.measurement` rows |
180
+ | `hr verdict` | Comprehensive verdict: capability averages + health + gates + assignment |
181
+ | `hr health` | Full-pool behavioral-health markdown table (DB-only, zero API calls) |
182
+ | `hr sweeps` | List sweeps from the DB with run/model/measurement counts |
183
+ | `hr calibrate` | Stage-0 anchor calibration engine (dry-run planning + live API passes) |
184
+ | `hr reference` | Read curated published-benchmark scores from `configs/knowledge.yaml` |
185
+ | `hr research` | Read qualitative findings from the same knowledge store |
186
+ | `hr publish` | Publish reports to Wiki.js (optional target; skips with exit 0 when unconfigured) |
187
+ | `hr recommend` | Seat recommendations from `configs/seats.yaml` + recent measurements |
188
+ | `hr status` | DB status: sweeps + latest-sweep capability means (DB-only) |
189
+ | `hr apply` | Bridge the latest verdict seating into a FastDraw preset |
190
+
191
+ The CLI has no global `--config` flag: configuration is resolved from the environment (see the table above) and from `configs/` relative to HR_HOME. Run `hr --help` and `hr <command> --help` for the full per-command flag list.
192
+
193
+ ## FastDraw Seam
194
+
195
+ FastDraw is the model-selection subpackage bundled at `fastdraw/`. It provides TUI-based preset management for agent model assignments and integrates with opencode through `hr apply`.
196
+
197
+ ### Subpackage Layout
198
+
199
+ ```
200
+ fastdraw/
201
+ server.ts # FastDraw HTTP server (preset API)
202
+ tui.ts # Terminal UI for preset management
203
+ package.json # npm manifest (standalone install)
204
+ test/ # Test suite
205
+ README.md # FastDraw-specific documentation
206
+ ```
207
+
208
+ ### The `hr apply` Contract
209
+
210
+ `hr apply` is the bridge between verdict seating and FastDraw presets. It works in three steps:
211
+
212
+ 1. Computes the latest per-seat verdict assignments
213
+ 2. Writes a named preset to `<opencode-config-dir>/fastdraw-presets.json`
214
+ 3. With `--set-state`, also writes `.fastdraw.json` for boot-time activation
215
+
216
+ ### Dual-File Registration
217
+
218
+ FastDraw has server and TUI components. Register the plugin in both opencode configuration files; registering only one silently omits the other component.
219
+
220
+ ```jsonc
221
+ // ~/.config/opencode/opencode.jsonc
222
+ { "plugin": ["opencode-fastdraw"] }
223
+ ```
224
+
225
+ ```json
226
+ // ~/.config/opencode/tui.json
227
+ { "plugin": ["opencode-fastdraw"] }
228
+ ```
229
+
230
+ The first loads the `fastdraw_*` agent tools; the second loads `/fastdraw` and the `<leader>m` key binding.
231
+
232
+ ## Layout
233
+
234
+ ```
235
+ harness/hr/ # repo root (pip install -e .)
236
+ configs/ # YAML config: deployable.yaml, fleet.yaml, hr.toml.example, knowledge.yaml, models.yaml, seats.yaml, thresholds.yaml (+ gitignored *.local.yaml overlays)
237
+ docs/ # bilingual documentation (en/, zh-CN/)
238
+ exports/ # generated artifacts (gitignored)
239
+ fastdraw/ # npm subpackage: FastDraw server, TUI, preset management
240
+ hr/ # Python package: the CLI and all business logic
241
+ adapters/ # provider adapters (anthropic-compat, openai-compat) + fleet routing
242
+ bench/ # benchmark batteries + stage0/stage1 sweep engines
243
+ graders/ # grading functions (factuality, reasoning, vision, tools)
244
+ items/ # item loaders for benchmark questions
245
+ scheduler/ # task scheduling (kept per Metis C1)
246
+ seats/ # seat taxonomy and profile helpers
247
+ stats/ # statistical aggregation for sweep results
248
+ itemrepo/ # git-versioned benchmark item repository by category
249
+ scripts/ # operational scripts (check_universal.sh, register_livebench_batteries.py, spread_probe.py, ...)
250
+ tests/ # pytest test suite
251
+ pyproject.toml # package manifest with CLI entry point
252
+ ```
253
+
254
+ ## Tests
255
+
256
+ ```bash
257
+ bash scripts/test.sh # hermetic offline suite, coverage >= 80%
258
+ bash scripts/test.sh --ci # lint, type checks, offline tests, wheel build
259
+ bash scripts/test.sh --with-db # explicit scratch-PostgreSQL integration suite
260
+ ```
261
+
262
+ The test suite is a release gate, not a collection of smoke tests.
263
+
264
+ | Test area | Purpose |
265
+ |-----------|---------|
266
+ | `tests/adapters/` | Validate provider endpoint resolution, protocol shaping, capability overlays, and error boundaries without network calls. |
267
+ | `tests/items/`, `tests/graders/` | Protect item parsing, content hashes, deterministic scoring, schema constraints, citations, and sandbox contracts. |
268
+ | `tests/test_calibrate*` | Protect anchor calibration, complete-tier checks, resume accounting, persistence, token caps, and `inconclusive`/`invalid` reporting. |
269
+ | `tests/test_stage0*`, `tests/test_stage1*`, `tests/test_bootstrap.py`, `tests/test_sequential.py` | Protect sweep planning, paired-score handling, resume keys, stopping rules, and finalist selection. |
270
+ | `tests/bench/` | Validate offline benchmark runners, request construction, scorer behavior, storage shape, and explicitly gated PostgreSQL end-to-end flows. |
271
+ | `tests/test_apply*`, `tests/test_cli*`, `tests/test_release_surface.py` | Protect user-facing CLI contracts, FastDraw export behavior, output locations, and package release surface. |
272
+ | `fastdraw/test/` | Validate OpenCode preset persistence, restore plans, comment-preserving config edits, TUI/server split behavior, and portable path handling. |
273
+
274
+ All offline tests run against hermetic fixtures and a per-test staging workspace: `HOME`, `OPENCODE_CONFIG_DIR`, `HR_HOME`, `HR_ITEMREPO`, and `HR_OUTPUT_DIR` are sealed into pytest temporary directories by `hr_sandbox` (`tests/conftest.py`). The session-level cleanliness guard snapshots `git status --porcelain` at session start and fails with the offending paths if a test writes into the repository. DB-marked tests require an explicit scratch database and are skipped by offline modes.
275
+
276
+ The quality gates are:
277
+
278
+ - `compileall`: import/syntax coverage for package, scripts, item builders, and tests.
279
+ - `ruff check hr scripts itemrepo`: undefined-name and fatal static checks.
280
+ - `basedpyright --level error hr scripts`: typed production-path validation.
281
+ - `pytest --cov=hr --cov-fail-under=80`: branch-aware package coverage floor.
282
+ - `scripts/check_universal.sh`: rejects machine-specific paths, prohibited model literals, and unsafe provider assumptions.
283
+ - `pip wheel --no-deps`: verifies the published package can be built.
284
+
285
+ Live API bench runs need real provider credentials from the opencode config:
286
+
287
+ ```bash
288
+ hr bench --model gpt-4o --battery reasoning
289
+ ```
290
+
291
+ ## Universality
292
+
293
+ This codebase targets the general class of autonomous LLM coding agents, not a specific product. The seat taxonomy (tier 1 through tier 4), the benchmark item categories (factuality, reasoning, vision, tool_a, tool_b), and the verdict pipeline (discover, bench, assign, verdict) apply to any agent that consumes LLM output and produces code artifacts.
294
+
295
+ Provider-specific hardcoding was removed during unification. The model fleet is derived at RUNTIME from opencode's live config (`opencode.jsonc` provider blocks: every `provider.*.models` entry becomes a fleet model, and the `npm` field derives the wire type); `configs/fleet.yaml` holds only OPTIONAL overrides (`wire_overrides` for registry-only providers, `scope_excludes`, `gateway_urls`), and `configs/deployable.yaml` `extra_deployable` is the only hand-maintained model list (models served outside the opencode config). Add a model to opencode's config and it flows into the sweep pools, discover and routing with zero file edits here. Knowledge data lives in `configs/models.yaml` (pricing/capabilities) and `configs/knowledge.yaml` (reference scores, findings), both with safe defaults for unknown models.
296
+
297
+ ## License
298
+
299
+ See `LICENSE`.
aihr-0.2.0/README.md ADDED
@@ -0,0 +1,261 @@
1
+ # HR: Agent Seat Matching and Capability Benchmarking
2
+
3
+ Unified harness that matches autonomous LLM coding agents to task-appropriate seats, runs capability benchmarks across model fleets, and emits deployment verdicts. One package, one database schema, and 13 CLI commands.
4
+
5
+ The English version is canonical. The Chinese version (`README.zh-CN.md`) is a faithful mirror. When the two diverge, the English text governs.
6
+
7
+ ## What HR Decides
8
+
9
+ HR is a decision-support plugin for assigning configured models to autonomous-agent seats. It does not claim that a model is universally "best". Its output is a bounded recommendation for a named seat or task, backed by a versioned item pool, the recorded model responses, health gates, and the policy in `configs/`.
10
+
11
+ The decision pipeline is:
12
+
13
+ 1. `hr discover` derives the candidate fleet from the live OpenCode configuration.
14
+ 2. `hr seed` registers seats, batteries, and item metadata in PostgreSQL.
15
+ 3. `hr calibrate` validates anchor-model difficulty bands against the item pool.
16
+ 4. `hr bench` or the Stage 0/Stage 1 sweep records scored measurements.
17
+ 5. `hr health`, `hr verdict`, and `hr recommend` apply capability, reliability, and seat gates.
18
+ 6. `hr apply` exports the accepted seat assignment to a FastDraw preset; it never changes a model assignment by itself unless explicitly requested.
19
+
20
+ ## Decision Statuses
21
+
22
+ Scores alone are not a safe decision contract. HR distinguishes these states:
23
+
24
+ | Status | Meaning | Allowed to rank or assign? |
25
+ |--------|---------|----------------------------|
26
+ | `pass` | All required items were measured and the configured rule passed. | Yes, subject to seat gates. |
27
+ | `fail` | All required items were measured and the configured rule failed. | No for that rule. |
28
+ | `inconclusive` | Samples are incomplete or an adapter/infrastructure failure occurred. | No; rerun or resume safely. |
29
+ | `invalid` | The configured item pool cannot support the requested rule. | No; repair the pool/configuration. |
30
+ | `not_applicable` | The model cannot perform the requested modality or tool protocol. | No for that capability; never coerce it to a zero-score capability failure. |
31
+
32
+ Calibration currently emits `pass`, `fail`, `inconclusive`, and `invalid`. Live benchmark and recommendation paths retain infrastructure incidents in the database and are being migrated to the same complete outcome contract. A token cap, a partial round, or a resumed run with missing measurements is evidence of uncertainty, not evidence that the model failed the task.
33
+
34
+ ## Methodology
35
+
36
+ ### Item pools and grading
37
+
38
+ `itemrepo/` is versioned test material. Every item has an item key, type, tier, payload, and grading specification. Batteries group items by capability, for example reasoning, factuality/hallucination, vision, `tool_a`, and `tool_b`. Graders are deterministic where possible: exact-match, schema, constraint, citation, and sandboxed unit-test graders. LLM judging is kept explicit because it introduces a second model and a second source of uncertainty.
39
+
40
+ Calibration uses anchor models and tier acceptance bands. Its purpose is not to select a production model. It detects a broken, missing, or difficulty-shifted item pool before that pool is used to decide seat assignments. A complete tier is required before a band can pass; malformed or missing evidence must not produce a vacuous pass.
41
+
42
+ ### Repeated measurement and separation
43
+
44
+ Stage 0 cheaply narrows the fleet. Stage 1 evaluates finalists against the full item banks. Each measurement is indexed by model, battery, round, item, and repetition so that repeated calls can be audited and resumed. Pairwise separation compares matched model/item observations; the item is the primary independent unit, and repetitions estimate gateway and generation variability.
45
+
46
+ Do not interpret a small point-score difference as a seat decision. A candidate should only displace another candidate when the relevant items are complete, the confidence/separation rule is met, and both candidates pass the seat's hard gates. The current implementation records pairwise bootstrap separation and sequential precision diagnostics. Planned hardening is documented in `docs/en/capability-prior.md`: per-model stopping, complete paired-round enforcement, and multiplicity-aware comparisons.
47
+
48
+ ### Health, constraints, and recommendation
49
+
50
+ Health is independent evidence, not a cosmetic penalty. It includes answer completion, self-consistency, tool reliability, and observed failures. A seat can impose required capabilities, context limits, and a health gate. A model without a required modality or one with insufficient evidence must be unassigned or reported as indeterminate rather than promoted by a fallback average.
51
+
52
+ Cost, latency, freshness, and uncertainty are part of the recommendation problem. `configs/models.yaml` supplies known price/capability facts; measurements supply observed behavior. Reference scores in `configs/knowledge.yaml` are priors, never replacements for a missing required live capability measurement.
53
+
54
+ ### Reproducibility and audit trail
55
+
56
+ The database stores sweeps, runs, measurements, infra incidents, separations, and calibration events. Preserve the item-pool hash, configuration revision, endpoint/model identity, timeout/retry policy, grader version, and random seed with every externally shared conclusion. Reports without that provenance are operational hints, not reproducible experiments.
57
+
58
+ ## Safety Rules
59
+
60
+ - The default `bash scripts/test.sh` and `--ci` modes explicitly remove inherited database credentials. They cannot silently use an ambient production DSN.
61
+ - `bash scripts/test.sh --with-db` accepts only an `hr_test_*` scratch database. It rejects names such as `wiki`.
62
+ - Generated artifacts resolve outside the repository by default. Tests seal `HOME`, OpenCode config, HR config, item repository, and output paths into temporary directories.
63
+ - A test session compares `git status --porcelain` before and after execution. Unexpected writes in the repository fail the suite.
64
+ - Production provider credentials belong in environment variables or local overlays, never in tracked YAML, `hr.toml`, test fixtures, or reports.
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ pip install .
70
+ ```
71
+
72
+ Source, editable, and wheel installs are supported. Packaged configuration resolves from the installation's `share/aihr` directory. Executable-code benchmarks fail closed unless Bubblewrap (`bwrap`) is installed; on Debian/Ubuntu use `sudo apt-get install bubblewrap`. If an older `hr-cli` or `hr-bench` package is already installed, remove it first:
73
+
74
+ ```bash
75
+ pip uninstall hr-cli hr-bench -y
76
+ pip install .
77
+ ```
78
+
79
+ ### Environment Variables
80
+
81
+ | Variable | Purpose | Default |
82
+ |----------|---------|---------|
83
+ | `HR_DSN` | Override the PostgreSQL connection string (preferred over `HR_DB_PASSWORD` + `db_*` fields) | unset |
84
+ | `HR_HOME` | Force an alternate config root (configs/, `hr.toml`, `itemrepo` are resolved from here) | repo root |
85
+ | `HR_COMPOSE_FILE` | Override the `docker compose` manifest that DB password resolution probes | unset |
86
+ | `HR_ITEMREPO` | Override the benchmark item repo directory | `HR_HOME/itemrepo` |
87
+ | `HR_OUTPUT_DIR` | Override the runtime output root for run artifacts | platform cache dir (see below) |
88
+
89
+ ### Output root (run artifacts)
90
+
91
+ Generated artifacts (bench exports, calibration reports, sweep dumps, …) NEVER land inside the repo tree. They resolve through `hr.config.output_root()`: `HR_OUTPUT_DIR` env var wins, otherwise the platform cache dir (`$XDG_CACHE_HOME/hr`, `~/Library/Caches/hr`, `%LOCALAPPDATA%/hr\Cache`), otherwise the system temp dir. CLI flags that name an explicit output path always win at the call site.
92
+
93
+ ### Configuration
94
+
95
+ Copy the example `hr.toml` if you need the DB / Wiki.js knobs:
96
+
97
+ ```bash
98
+ cp configs/hr.toml.example hr.toml
99
+ ```
100
+
101
+ There is no single "source of truth" file — configuration is split by concern across `configs/`, plus the runtime opencode config:
102
+
103
+ ### Local overlays (`configs/*.local.yaml`)
104
+
105
+ The tracked configs ship ZERO real deployment values (placeholder examples
106
+ where a value is machine-specific). A live machine's real values live in the
107
+ gitignored local overlays — `configs/seats.local.yaml`, `configs/fleet.local.yaml`,
108
+ `configs/deployable.local.yaml`, `configs/models.local.yaml` — which
109
+ `hr.config.load_yaml` deep-merges over the tracked files automatically:
110
+ **local wins per key; dicts merge recursively; lists are replaced, never
111
+ merged.** A missing overlay is normal (the tracked file is used as-is).
112
+
113
+ First-install: `cp configs/seats.yaml configs/seats.local.yaml`,
114
+ `cp configs/fleet.yaml configs/fleet.local.yaml`,
115
+ `cp configs/deployable.yaml configs/deployable.local.yaml` (and
116
+ `configs/models.yaml` → `models.local.yaml` if your gateway facts differ),
117
+ then fill in your real anchors, wire overrides, gateway URLs and
118
+ `extra_deployable` list. Never edit deployment values into the tracked
119
+ files — *any* `.local.yaml` is safe for real values, *nothing else* is.
120
+
121
+ The per-file split:
122
+
123
+ - `configs/thresholds.yaml` — numeric sweep and gate thresholds (stage0 budgets, half-widths, acceptance bands).
124
+ - `configs/models.yaml` — model pricing and the capability overlay (thinking/vision), keyed by bare model slug; unknown models get safe defaults.
125
+ - `configs/knowledge.yaml` — curated reference scores and qualitative research findings, keyed by bare model slug (unknown models are skipped).
126
+ - `configs/fleet.yaml` — OPTIONAL overrides for the dynamic fleet: `wire_overrides`, `scope_excludes`, and `gateway_urls` (base URLs for registry-only providers).
127
+ - `configs/seats.yaml` — seat definitions, per-seat `primary_capabilities`, and the stage-0 `calibration_anchors`.
128
+ - `configs/deployable.yaml` — `extra_deployable`: models served outside the opencode config (the only hand-maintained model list).
129
+ - `configs/hr.toml.example` — template for the root `hr.toml` (DB connection + optional Wiki.js publish target). Secrets are NEVER stored here: they come from the environment (`HR_DSN`, `HR_DB_PASSWORD`, provider keys).
130
+
131
+ The model fleet itself is not declared in this repo: it is derived at runtime from the opencode config (`opencode.jsonc` provider blocks) and merged with the `deployable.yaml` extras — see Universality below.
132
+
133
+ ## CLI Map
134
+
135
+ Thirteen commands, each targeting a specific concern. Legacy v1 commands (`evaluate`, `report`, `run_all`) were retired. `hr verdict` supersedes the retired evaluation path.
136
+
137
+ | Command | Purpose |
138
+ |---------|---------|
139
+ | `hr discover` | Enumerate providers/models from `opencode.jsonc` into `hr` (scope + auth presence) |
140
+ | `hr seed` | Initialize the schema and seed canonical seat definitions |
141
+ | `hr bench` | Run the live capability benchmarks and record `hr.measurement` rows |
142
+ | `hr verdict` | Comprehensive verdict: capability averages + health + gates + assignment |
143
+ | `hr health` | Full-pool behavioral-health markdown table (DB-only, zero API calls) |
144
+ | `hr sweeps` | List sweeps from the DB with run/model/measurement counts |
145
+ | `hr calibrate` | Stage-0 anchor calibration engine (dry-run planning + live API passes) |
146
+ | `hr reference` | Read curated published-benchmark scores from `configs/knowledge.yaml` |
147
+ | `hr research` | Read qualitative findings from the same knowledge store |
148
+ | `hr publish` | Publish reports to Wiki.js (optional target; skips with exit 0 when unconfigured) |
149
+ | `hr recommend` | Seat recommendations from `configs/seats.yaml` + recent measurements |
150
+ | `hr status` | DB status: sweeps + latest-sweep capability means (DB-only) |
151
+ | `hr apply` | Bridge the latest verdict seating into a FastDraw preset |
152
+
153
+ The CLI has no global `--config` flag: configuration is resolved from the environment (see the table above) and from `configs/` relative to HR_HOME. Run `hr --help` and `hr <command> --help` for the full per-command flag list.
154
+
155
+ ## FastDraw Seam
156
+
157
+ FastDraw is the model-selection subpackage bundled at `fastdraw/`. It provides TUI-based preset management for agent model assignments and integrates with opencode through `hr apply`.
158
+
159
+ ### Subpackage Layout
160
+
161
+ ```
162
+ fastdraw/
163
+ server.ts # FastDraw HTTP server (preset API)
164
+ tui.ts # Terminal UI for preset management
165
+ package.json # npm manifest (standalone install)
166
+ test/ # Test suite
167
+ README.md # FastDraw-specific documentation
168
+ ```
169
+
170
+ ### The `hr apply` Contract
171
+
172
+ `hr apply` is the bridge between verdict seating and FastDraw presets. It works in three steps:
173
+
174
+ 1. Computes the latest per-seat verdict assignments
175
+ 2. Writes a named preset to `<opencode-config-dir>/fastdraw-presets.json`
176
+ 3. With `--set-state`, also writes `.fastdraw.json` for boot-time activation
177
+
178
+ ### Dual-File Registration
179
+
180
+ FastDraw has server and TUI components. Register the plugin in both opencode configuration files; registering only one silently omits the other component.
181
+
182
+ ```jsonc
183
+ // ~/.config/opencode/opencode.jsonc
184
+ { "plugin": ["opencode-fastdraw"] }
185
+ ```
186
+
187
+ ```json
188
+ // ~/.config/opencode/tui.json
189
+ { "plugin": ["opencode-fastdraw"] }
190
+ ```
191
+
192
+ The first loads the `fastdraw_*` agent tools; the second loads `/fastdraw` and the `<leader>m` key binding.
193
+
194
+ ## Layout
195
+
196
+ ```
197
+ harness/hr/ # repo root (pip install -e .)
198
+ configs/ # YAML config: deployable.yaml, fleet.yaml, hr.toml.example, knowledge.yaml, models.yaml, seats.yaml, thresholds.yaml (+ gitignored *.local.yaml overlays)
199
+ docs/ # bilingual documentation (en/, zh-CN/)
200
+ exports/ # generated artifacts (gitignored)
201
+ fastdraw/ # npm subpackage: FastDraw server, TUI, preset management
202
+ hr/ # Python package: the CLI and all business logic
203
+ adapters/ # provider adapters (anthropic-compat, openai-compat) + fleet routing
204
+ bench/ # benchmark batteries + stage0/stage1 sweep engines
205
+ graders/ # grading functions (factuality, reasoning, vision, tools)
206
+ items/ # item loaders for benchmark questions
207
+ scheduler/ # task scheduling (kept per Metis C1)
208
+ seats/ # seat taxonomy and profile helpers
209
+ stats/ # statistical aggregation for sweep results
210
+ itemrepo/ # git-versioned benchmark item repository by category
211
+ scripts/ # operational scripts (check_universal.sh, register_livebench_batteries.py, spread_probe.py, ...)
212
+ tests/ # pytest test suite
213
+ pyproject.toml # package manifest with CLI entry point
214
+ ```
215
+
216
+ ## Tests
217
+
218
+ ```bash
219
+ bash scripts/test.sh # hermetic offline suite, coverage >= 80%
220
+ bash scripts/test.sh --ci # lint, type checks, offline tests, wheel build
221
+ bash scripts/test.sh --with-db # explicit scratch-PostgreSQL integration suite
222
+ ```
223
+
224
+ The test suite is a release gate, not a collection of smoke tests.
225
+
226
+ | Test area | Purpose |
227
+ |-----------|---------|
228
+ | `tests/adapters/` | Validate provider endpoint resolution, protocol shaping, capability overlays, and error boundaries without network calls. |
229
+ | `tests/items/`, `tests/graders/` | Protect item parsing, content hashes, deterministic scoring, schema constraints, citations, and sandbox contracts. |
230
+ | `tests/test_calibrate*` | Protect anchor calibration, complete-tier checks, resume accounting, persistence, token caps, and `inconclusive`/`invalid` reporting. |
231
+ | `tests/test_stage0*`, `tests/test_stage1*`, `tests/test_bootstrap.py`, `tests/test_sequential.py` | Protect sweep planning, paired-score handling, resume keys, stopping rules, and finalist selection. |
232
+ | `tests/bench/` | Validate offline benchmark runners, request construction, scorer behavior, storage shape, and explicitly gated PostgreSQL end-to-end flows. |
233
+ | `tests/test_apply*`, `tests/test_cli*`, `tests/test_release_surface.py` | Protect user-facing CLI contracts, FastDraw export behavior, output locations, and package release surface. |
234
+ | `fastdraw/test/` | Validate OpenCode preset persistence, restore plans, comment-preserving config edits, TUI/server split behavior, and portable path handling. |
235
+
236
+ All offline tests run against hermetic fixtures and a per-test staging workspace: `HOME`, `OPENCODE_CONFIG_DIR`, `HR_HOME`, `HR_ITEMREPO`, and `HR_OUTPUT_DIR` are sealed into pytest temporary directories by `hr_sandbox` (`tests/conftest.py`). The session-level cleanliness guard snapshots `git status --porcelain` at session start and fails with the offending paths if a test writes into the repository. DB-marked tests require an explicit scratch database and are skipped by offline modes.
237
+
238
+ The quality gates are:
239
+
240
+ - `compileall`: import/syntax coverage for package, scripts, item builders, and tests.
241
+ - `ruff check hr scripts itemrepo`: undefined-name and fatal static checks.
242
+ - `basedpyright --level error hr scripts`: typed production-path validation.
243
+ - `pytest --cov=hr --cov-fail-under=80`: branch-aware package coverage floor.
244
+ - `scripts/check_universal.sh`: rejects machine-specific paths, prohibited model literals, and unsafe provider assumptions.
245
+ - `pip wheel --no-deps`: verifies the published package can be built.
246
+
247
+ Live API bench runs need real provider credentials from the opencode config:
248
+
249
+ ```bash
250
+ hr bench --model gpt-4o --battery reasoning
251
+ ```
252
+
253
+ ## Universality
254
+
255
+ This codebase targets the general class of autonomous LLM coding agents, not a specific product. The seat taxonomy (tier 1 through tier 4), the benchmark item categories (factuality, reasoning, vision, tool_a, tool_b), and the verdict pipeline (discover, bench, assign, verdict) apply to any agent that consumes LLM output and produces code artifacts.
256
+
257
+ Provider-specific hardcoding was removed during unification. The model fleet is derived at RUNTIME from opencode's live config (`opencode.jsonc` provider blocks: every `provider.*.models` entry becomes a fleet model, and the `npm` field derives the wire type); `configs/fleet.yaml` holds only OPTIONAL overrides (`wire_overrides` for registry-only providers, `scope_excludes`, `gateway_urls`), and `configs/deployable.yaml` `extra_deployable` is the only hand-maintained model list (models served outside the opencode config). Add a model to opencode's config and it flows into the sweep pools, discover and routing with zero file edits here. Knowledge data lives in `configs/models.yaml` (pricing/capabilities) and `configs/knowledge.yaml` (reference scores, findings), both with safe defaults for unknown models.
258
+
259
+ ## License
260
+
261
+ See `LICENSE`.