freeweight 1.0.0rc1__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 (421) hide show
  1. freeweight-1.0.0rc1/.editorconfig +23 -0
  2. freeweight-1.0.0rc1/.github/workflows/ci.yml +199 -0
  3. freeweight-1.0.0rc1/.github/workflows/nightly.yml +41 -0
  4. freeweight-1.0.0rc1/.github/workflows/release.yml +58 -0
  5. freeweight-1.0.0rc1/.gitignore +100 -0
  6. freeweight-1.0.0rc1/.gitleaks.toml +38 -0
  7. freeweight-1.0.0rc1/.importlinter +40 -0
  8. freeweight-1.0.0rc1/.pre-commit-config.yaml +22 -0
  9. freeweight-1.0.0rc1/CHANGELOG.md +899 -0
  10. freeweight-1.0.0rc1/CONTRIBUTING.md +50 -0
  11. freeweight-1.0.0rc1/LICENSE +201 -0
  12. freeweight-1.0.0rc1/PHASE10.diff +17158 -0
  13. freeweight-1.0.0rc1/PHASE10_ISSUES.md +496 -0
  14. freeweight-1.0.0rc1/PHASE11_ISSUES.md +214 -0
  15. freeweight-1.0.0rc1/PHASE7_ISSUES.md +160 -0
  16. freeweight-1.0.0rc1/PHASE8_DECISIONS.md +318 -0
  17. freeweight-1.0.0rc1/PHASE8_ISSUES.md +336 -0
  18. freeweight-1.0.0rc1/PHASE9_ISSUES.md +171 -0
  19. freeweight-1.0.0rc1/PKG-INFO +107 -0
  20. freeweight-1.0.0rc1/README.md +59 -0
  21. freeweight-1.0.0rc1/SECURITY.md +39 -0
  22. freeweight-1.0.0rc1/docs/README.md +27 -0
  23. freeweight-1.0.0rc1/docs/apps/freeweight/api.md +362 -0
  24. freeweight-1.0.0rc1/docs/apps/freeweight/benchmark-catalog.md +569 -0
  25. freeweight-1.0.0rc1/docs/apps/freeweight/data-model.md +566 -0
  26. freeweight-1.0.0rc1/docs/apps/freeweight/development-plan.md +1220 -0
  27. freeweight-1.0.0rc1/docs/apps/freeweight/risks.md +125 -0
  28. freeweight-1.0.0rc1/docs/apps/freeweight/spec.md +652 -0
  29. freeweight-1.0.0rc1/docs/apps/freeweight/subjective-goals.md +499 -0
  30. freeweight-1.0.0rc1/docs/configuration.md +187 -0
  31. freeweight-1.0.0rc1/docs/image.png +0 -0
  32. freeweight-1.0.0rc1/docs/openapi.json +3156 -0
  33. freeweight-1.0.0rc1/pyproject.toml +149 -0
  34. freeweight-1.0.0rc1/requirements/README.md +63 -0
  35. freeweight-1.0.0rc1/requirements/release.in +6 -0
  36. freeweight-1.0.0rc1/requirements/release.lock +493 -0
  37. freeweight-1.0.0rc1/scripts/generate_config_reference.py +243 -0
  38. freeweight-1.0.0rc1/scripts/generate_openapi_snapshot.py +71 -0
  39. freeweight-1.0.0rc1/scripts/sync_docs.py +104 -0
  40. freeweight-1.0.0rc1/src/freeweight/__about__.py +1 -0
  41. freeweight-1.0.0rc1/src/freeweight/__main__.py +12 -0
  42. freeweight-1.0.0rc1/src/freeweight/benchmarks/agent/benchmark.py +84 -0
  43. freeweight-1.0.0rc1/src/freeweight/benchmarks/agent/cases.json +91 -0
  44. freeweight-1.0.0rc1/src/freeweight/benchmarks/agent/manifest.json +96 -0
  45. freeweight-1.0.0rc1/src/freeweight/benchmarks/audit/__init__.py +1 -0
  46. freeweight-1.0.0rc1/src/freeweight/benchmarks/audit/benchmark.py +171 -0
  47. freeweight-1.0.0rc1/src/freeweight/benchmarks/audit/cases.json +26 -0
  48. freeweight-1.0.0rc1/src/freeweight/benchmarks/audit/manifest.json +98 -0
  49. freeweight-1.0.0rc1/src/freeweight/benchmarks/corpora/__init__.py +73 -0
  50. freeweight-1.0.0rc1/src/freeweight/benchmarks/corpora/audit_code.json +160 -0
  51. freeweight-1.0.0rc1/src/freeweight/benchmarks/corpora/critique_answers.json +144 -0
  52. freeweight-1.0.0rc1/src/freeweight/benchmarks/corpora/judge_comparisons.json +105 -0
  53. freeweight-1.0.0rc1/src/freeweight/benchmarks/corpora/long_context_needles.json +125 -0
  54. freeweight-1.0.0rc1/src/freeweight/benchmarks/critique/__init__.py +1 -0
  55. freeweight-1.0.0rc1/src/freeweight/benchmarks/critique/benchmark.py +135 -0
  56. freeweight-1.0.0rc1/src/freeweight/benchmarks/critique/cases.json +33 -0
  57. freeweight-1.0.0rc1/src/freeweight/benchmarks/critique/manifest.json +97 -0
  58. freeweight-1.0.0rc1/src/freeweight/benchmarks/echo/benchmark.py +227 -0
  59. freeweight-1.0.0rc1/src/freeweight/benchmarks/echo/manifest.json +29 -0
  60. freeweight-1.0.0rc1/src/freeweight/benchmarks/energy/benchmark.py +460 -0
  61. freeweight-1.0.0rc1/src/freeweight/benchmarks/energy/energy.py +345 -0
  62. freeweight-1.0.0rc1/src/freeweight/benchmarks/energy/manifest.json +111 -0
  63. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/inventory.json +4 -0
  64. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/records.json +5 -0
  65. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/repo/README.md +5 -0
  66. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/repo/pkg/inventory.py +14 -0
  67. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/repo/pkg/pricing.py +14 -0
  68. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/repo/tests/test_pricing.py +8 -0
  69. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/tables.json +11 -0
  70. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/tests.json +15 -0
  71. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/data/tools.json +127 -0
  72. freeweight-1.0.0rc1/src/freeweight/benchmarks/fixtures/tools.py +700 -0
  73. freeweight-1.0.0rc1/src/freeweight/benchmarks/goal/__init__.py +1 -0
  74. freeweight-1.0.0rc1/src/freeweight/benchmarks/goal/runner.py +639 -0
  75. freeweight-1.0.0rc1/src/freeweight/benchmarks/instruction_following/benchmark.py +108 -0
  76. freeweight-1.0.0rc1/src/freeweight/benchmarks/instruction_following/cases.json +171 -0
  77. freeweight-1.0.0rc1/src/freeweight/benchmarks/instruction_following/manifest.json +87 -0
  78. freeweight-1.0.0rc1/src/freeweight/benchmarks/interaction.py +370 -0
  79. freeweight-1.0.0rc1/src/freeweight/benchmarks/judge/__init__.py +1 -0
  80. freeweight-1.0.0rc1/src/freeweight/benchmarks/judge/benchmark.py +262 -0
  81. freeweight-1.0.0rc1/src/freeweight/benchmarks/judge/cases.json +67 -0
  82. freeweight-1.0.0rc1/src/freeweight/benchmarks/judge/manifest.json +126 -0
  83. freeweight-1.0.0rc1/src/freeweight/benchmarks/judge/session.py +237 -0
  84. freeweight-1.0.0rc1/src/freeweight/benchmarks/loading.py +260 -0
  85. freeweight-1.0.0rc1/src/freeweight/benchmarks/long_context/__init__.py +1 -0
  86. freeweight-1.0.0rc1/src/freeweight/benchmarks/long_context/benchmark.py +335 -0
  87. freeweight-1.0.0rc1/src/freeweight/benchmarks/long_context/cases.json +47 -0
  88. freeweight-1.0.0rc1/src/freeweight/benchmarks/long_context/haystack.py +181 -0
  89. freeweight-1.0.0rc1/src/freeweight/benchmarks/long_context/manifest.json +72 -0
  90. freeweight-1.0.0rc1/src/freeweight/benchmarks/long_context/scoring.py +88 -0
  91. freeweight-1.0.0rc1/src/freeweight/benchmarks/memory_kv/benchmark.py +599 -0
  92. freeweight-1.0.0rc1/src/freeweight/benchmarks/memory_kv/kv.py +438 -0
  93. freeweight-1.0.0rc1/src/freeweight/benchmarks/memory_kv/manifest.json +99 -0
  94. freeweight-1.0.0rc1/src/freeweight/benchmarks/performance/.gitkeep +0 -0
  95. freeweight-1.0.0rc1/src/freeweight/benchmarks/performance/benchmark.py +502 -0
  96. freeweight-1.0.0rc1/src/freeweight/benchmarks/performance/manifest.json +112 -0
  97. freeweight-1.0.0rc1/src/freeweight/benchmarks/reliability/benchmark.py +425 -0
  98. freeweight-1.0.0rc1/src/freeweight/benchmarks/reliability/cases.json +42 -0
  99. freeweight-1.0.0rc1/src/freeweight/benchmarks/reliability/manifest.json +111 -0
  100. freeweight-1.0.0rc1/src/freeweight/benchmarks/reliability/reliability.py +237 -0
  101. freeweight-1.0.0rc1/src/freeweight/benchmarks/structured_output/benchmark.py +100 -0
  102. freeweight-1.0.0rc1/src/freeweight/benchmarks/structured_output/cases.json +92 -0
  103. freeweight-1.0.0rc1/src/freeweight/benchmarks/structured_output/manifest.json +94 -0
  104. freeweight-1.0.0rc1/src/freeweight/benchmarks/token_economy/.gitkeep +0 -0
  105. freeweight-1.0.0rc1/src/freeweight/benchmarks/token_economy/benchmark.py +341 -0
  106. freeweight-1.0.0rc1/src/freeweight/benchmarks/token_economy/manifest.json +99 -0
  107. freeweight-1.0.0rc1/src/freeweight/benchmarks/tool_recovery/benchmark.py +85 -0
  108. freeweight-1.0.0rc1/src/freeweight/benchmarks/tool_recovery/cases.json +95 -0
  109. freeweight-1.0.0rc1/src/freeweight/benchmarks/tool_recovery/manifest.json +82 -0
  110. freeweight-1.0.0rc1/src/freeweight/benchmarks/tool_use/benchmark.py +123 -0
  111. freeweight-1.0.0rc1/src/freeweight/benchmarks/tool_use/cases.json +168 -0
  112. freeweight-1.0.0rc1/src/freeweight/benchmarks/tool_use/manifest.json +124 -0
  113. freeweight-1.0.0rc1/src/freeweight/bootstrap.py +114 -0
  114. freeweight-1.0.0rc1/src/freeweight/cli/commands/config.py +128 -0
  115. freeweight-1.0.0rc1/src/freeweight/cli/commands/db.py +299 -0
  116. freeweight-1.0.0rc1/src/freeweight/cli/commands/evidence.py +296 -0
  117. freeweight-1.0.0rc1/src/freeweight/cli/commands/external.py +4 -0
  118. freeweight-1.0.0rc1/src/freeweight/cli/commands/goals.py +970 -0
  119. freeweight-1.0.0rc1/src/freeweight/cli/commands/judges.py +183 -0
  120. freeweight-1.0.0rc1/src/freeweight/cli/commands/models.py +279 -0
  121. freeweight-1.0.0rc1/src/freeweight/cli/commands/prompts.py +233 -0
  122. freeweight-1.0.0rc1/src/freeweight/cli/commands/results.py +579 -0
  123. freeweight-1.0.0rc1/src/freeweight/cli/commands/runs.py +631 -0
  124. freeweight-1.0.0rc1/src/freeweight/cli/commands/system.py +126 -0
  125. freeweight-1.0.0rc1/src/freeweight/cli/main.py +80 -0
  126. freeweight-1.0.0rc1/src/freeweight/config/capability_weights.toml +164 -0
  127. freeweight-1.0.0rc1/src/freeweight/config.py +1173 -0
  128. freeweight-1.0.0rc1/src/freeweight/domain/aggregation.py +504 -0
  129. freeweight-1.0.0rc1/src/freeweight/domain/agreement.py +481 -0
  130. freeweight-1.0.0rc1/src/freeweight/domain/benchmark.py +415 -0
  131. freeweight-1.0.0rc1/src/freeweight/domain/calibration.py +392 -0
  132. freeweight-1.0.0rc1/src/freeweight/domain/capability_mapping.py +364 -0
  133. freeweight-1.0.0rc1/src/freeweight/domain/comparison.py +455 -0
  134. freeweight-1.0.0rc1/src/freeweight/domain/confidence.py +629 -0
  135. freeweight-1.0.0rc1/src/freeweight/domain/goals/__init__.py +18 -0
  136. freeweight-1.0.0rc1/src/freeweight/domain/goals/composite.py +162 -0
  137. freeweight-1.0.0rc1/src/freeweight/domain/goals/criteria.py +362 -0
  138. freeweight-1.0.0rc1/src/freeweight/domain/goals/hashing.py +113 -0
  139. freeweight-1.0.0rc1/src/freeweight/domain/goals/lint.py +490 -0
  140. freeweight-1.0.0rc1/src/freeweight/domain/goals/pack.py +650 -0
  141. freeweight-1.0.0rc1/src/freeweight/domain/judging.py +662 -0
  142. freeweight-1.0.0rc1/src/freeweight/domain/jury.py +210 -0
  143. freeweight-1.0.0rc1/src/freeweight/domain/metrics.py +500 -0
  144. freeweight-1.0.0rc1/src/freeweight/domain/provenance.py +391 -0
  145. freeweight-1.0.0rc1/src/freeweight/domain/run_state.py +262 -0
  146. freeweight-1.0.0rc1/src/freeweight/domain/scorers/agent.py +174 -0
  147. freeweight-1.0.0rc1/src/freeweight/domain/scorers/audit.py +404 -0
  148. freeweight-1.0.0rc1/src/freeweight/domain/scorers/critique.py +295 -0
  149. freeweight-1.0.0rc1/src/freeweight/domain/scorers/exact.py +191 -0
  150. freeweight-1.0.0rc1/src/freeweight/domain/scorers/judge.py +418 -0
  151. freeweight-1.0.0rc1/src/freeweight/domain/scorers/judged.py +340 -0
  152. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rule.py +460 -0
  153. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/__init__.py +322 -0
  154. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/length.py +218 -0
  155. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/phrases.py +143 -0
  156. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/pov_tense.py +272 -0
  157. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/punctuation.py +109 -0
  158. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/readability.py +158 -0
  159. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/reference.py +369 -0
  160. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/regex.py +140 -0
  161. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/repetition.py +117 -0
  162. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/structure.py +173 -0
  163. freeweight-1.0.0rc1/src/freeweight/domain/scorers/rules/vocabulary.py +129 -0
  164. freeweight-1.0.0rc1/src/freeweight/domain/scorers/schema.py +421 -0
  165. freeweight-1.0.0rc1/src/freeweight/domain/scorers/tools.py +571 -0
  166. freeweight-1.0.0rc1/src/freeweight/domain/scoring.py +129 -0
  167. freeweight-1.0.0rc1/src/freeweight/domain/statistics.py +566 -0
  168. freeweight-1.0.0rc1/src/freeweight/external/adapters/.gitkeep +0 -0
  169. freeweight-1.0.0rc1/src/freeweight/external/environment.py +4 -0
  170. freeweight-1.0.0rc1/src/freeweight/external/framework.py +4 -0
  171. freeweight-1.0.0rc1/src/freeweight/external/sandbox.py +4 -0
  172. freeweight-1.0.0rc1/src/freeweight/goals/__init__.py +10 -0
  173. freeweight-1.0.0rc1/src/freeweight/goals/starters/__init__.py +319 -0
  174. freeweight-1.0.0rc1/src/freeweight/goals/starters/brand_voice/calibration.json +115 -0
  175. freeweight-1.0.0rc1/src/freeweight/goals/starters/brand_voice/goal.json +146 -0
  176. freeweight-1.0.0rc1/src/freeweight/goals/starters/brand_voice/tasks/001.json +37 -0
  177. freeweight-1.0.0rc1/src/freeweight/goals/starters/brand_voice/tasks/002.json +37 -0
  178. freeweight-1.0.0rc1/src/freeweight/goals/starters/creative_voice/calibration.json +195 -0
  179. freeweight-1.0.0rc1/src/freeweight/goals/starters/creative_voice/goal.json +122 -0
  180. freeweight-1.0.0rc1/src/freeweight/goals/starters/creative_voice/tasks/001.json +37 -0
  181. freeweight-1.0.0rc1/src/freeweight/goals/starters/creative_voice/tasks/002.json +37 -0
  182. freeweight-1.0.0rc1/src/freeweight/goals/starters/creative_voice/tasks/003.json +37 -0
  183. freeweight-1.0.0rc1/src/freeweight/goals/starters/summary_faithfulness/calibration.json +115 -0
  184. freeweight-1.0.0rc1/src/freeweight/goals/starters/summary_faithfulness/goal.json +97 -0
  185. freeweight-1.0.0rc1/src/freeweight/goals/starters/summary_faithfulness/tasks/001.json +71 -0
  186. freeweight-1.0.0rc1/src/freeweight/goals/starters/summary_faithfulness/tasks/002.json +70 -0
  187. freeweight-1.0.0rc1/src/freeweight/goals/starters/technical_explanation/calibration.json +195 -0
  188. freeweight-1.0.0rc1/src/freeweight/goals/starters/technical_explanation/goal.json +99 -0
  189. freeweight-1.0.0rc1/src/freeweight/goals/starters/technical_explanation/tasks/001.json +37 -0
  190. freeweight-1.0.0rc1/src/freeweight/goals/starters/technical_explanation/tasks/002.json +37 -0
  191. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/backup.py +609 -0
  192. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/base.py +51 -0
  193. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/engine.py +209 -0
  194. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/errors.py +83 -0
  195. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migration.py +325 -0
  196. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/.gitkeep +0 -0
  197. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/env.py +45 -0
  198. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/script.py.mako +26 -0
  199. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/versions/0001_initial_schema.py +198 -0
  200. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/versions/0002_run_engine_tables.py +440 -0
  201. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/versions/0003_telemetry_tables.py +120 -0
  202. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/versions/0004_tool_calls.py +76 -0
  203. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/versions/0005_goal_tables.py +182 -0
  204. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/versions/0006_calibration_tables.py +234 -0
  205. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/migrations/versions/0007_capability_evidence.py +184 -0
  206. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/models.py +237 -0
  207. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/models_evidence.py +139 -0
  208. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/models_goals.py +393 -0
  209. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/models_runs.py +602 -0
  210. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/calibration.py +237 -0
  211. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/evidence.py +134 -0
  212. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/goals.py +222 -0
  213. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/machines.py +141 -0
  214. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/model_descriptors.py +130 -0
  215. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/models.py +375 -0
  216. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/runs.py +917 -0
  217. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/settings.py +53 -0
  218. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/repositories/telemetry.py +118 -0
  219. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/session.py +71 -0
  220. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/types.py +116 -0
  221. freeweight-1.0.0rc1/src/freeweight/infrastructure/db/upsert.py +85 -0
  222. freeweight-1.0.0rc1/src/freeweight/infrastructure/providers/factory.py +67 -0
  223. freeweight-1.0.0rc1/src/freeweight/observability/logging.py +144 -0
  224. freeweight-1.0.0rc1/src/freeweight/prompts/.gitkeep +0 -0
  225. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/agent.task.v1.json +42 -0
  226. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/audit.detect_defects.v1.json +50 -0
  227. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/critique.review.v1.json +45 -0
  228. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/energy.workload.v1.json +42 -0
  229. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/instruction_following.constrained.v1.json +42 -0
  230. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/judge.answer.v1.json +40 -0
  231. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/judge.pairwise.v1.json +51 -0
  232. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/long_context.retrieve.v1.json +45 -0
  233. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/memory_kv.context_probe.v1.json +42 -0
  234. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/performance.probe.v1.json +42 -0
  235. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/reliability.probe.v1.json +37 -0
  236. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/structured_output.repair.v1.json +42 -0
  237. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/structured_output.schema.v1.json +42 -0
  238. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/token_economy.probe.v1.json +37 -0
  239. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/tool_recovery.task.v1.json +37 -0
  240. freeweight-1.0.0rc1/src/freeweight/prompts/benchmarks/tool_use.task.v1.json +37 -0
  241. freeweight-1.0.0rc1/src/freeweight/prompts/goals/judge.pairwise.v1.json +56 -0
  242. freeweight-1.0.0rc1/src/freeweight/prompts/goals/judge.rubric.v1.json +74 -0
  243. freeweight-1.0.0rc1/src/freeweight/prompts/manifest.json +99 -0
  244. freeweight-1.0.0rc1/src/freeweight/services/calibration.py +1621 -0
  245. freeweight-1.0.0rc1/src/freeweight/services/comparison.py +824 -0
  246. freeweight-1.0.0rc1/src/freeweight/services/database.py +425 -0
  247. freeweight-1.0.0rc1/src/freeweight/services/database_admin.py +814 -0
  248. freeweight-1.0.0rc1/src/freeweight/services/events.py +354 -0
  249. freeweight-1.0.0rc1/src/freeweight/services/evidence.py +1975 -0
  250. freeweight-1.0.0rc1/src/freeweight/services/export.py +1396 -0
  251. freeweight-1.0.0rc1/src/freeweight/services/goals.py +1086 -0
  252. freeweight-1.0.0rc1/src/freeweight/services/health.py +320 -0
  253. freeweight-1.0.0rc1/src/freeweight/services/inventory.py +164 -0
  254. freeweight-1.0.0rc1/src/freeweight/services/jury.py +599 -0
  255. freeweight-1.0.0rc1/src/freeweight/services/machine.py +116 -0
  256. freeweight-1.0.0rc1/src/freeweight/services/models.py +621 -0
  257. freeweight-1.0.0rc1/src/freeweight/services/prompts.py +943 -0
  258. freeweight-1.0.0rc1/src/freeweight/services/results.py +1356 -0
  259. freeweight-1.0.0rc1/src/freeweight/services/runs.py +4235 -0
  260. freeweight-1.0.0rc1/src/freeweight/services/scheduler.py +326 -0
  261. freeweight-1.0.0rc1/src/freeweight/services/settings.py +480 -0
  262. freeweight-1.0.0rc1/src/freeweight/services/telemetry.py +209 -0
  263. freeweight-1.0.0rc1/src/freeweight/services/telemetry_recording.py +641 -0
  264. freeweight-1.0.0rc1/src/freeweight/services/wizard.py +1178 -0
  265. freeweight-1.0.0rc1/src/freeweight/web/app.py +232 -0
  266. freeweight-1.0.0rc1/src/freeweight/web/errors.py +180 -0
  267. freeweight-1.0.0rc1/src/freeweight/web/middleware.py +166 -0
  268. freeweight-1.0.0rc1/src/freeweight/web/rendering.py +77 -0
  269. freeweight-1.0.0rc1/src/freeweight/web/routes/benchmarks.py +113 -0
  270. freeweight-1.0.0rc1/src/freeweight/web/routes/calibration.py +335 -0
  271. freeweight-1.0.0rc1/src/freeweight/web/routes/compare.py +205 -0
  272. freeweight-1.0.0rc1/src/freeweight/web/routes/dashboard.py +94 -0
  273. freeweight-1.0.0rc1/src/freeweight/web/routes/database.py +294 -0
  274. freeweight-1.0.0rc1/src/freeweight/web/routes/evidence.py +261 -0
  275. freeweight-1.0.0rc1/src/freeweight/web/routes/goals.py +375 -0
  276. freeweight-1.0.0rc1/src/freeweight/web/routes/grading.py +114 -0
  277. freeweight-1.0.0rc1/src/freeweight/web/routes/machines.py +120 -0
  278. freeweight-1.0.0rc1/src/freeweight/web/routes/models.py +322 -0
  279. freeweight-1.0.0rc1/src/freeweight/web/routes/results.py +443 -0
  280. freeweight-1.0.0rc1/src/freeweight/web/routes/runs.py +791 -0
  281. freeweight-1.0.0rc1/src/freeweight/web/routes/settings.py +169 -0
  282. freeweight-1.0.0rc1/src/freeweight/web/routes/sources.py +4 -0
  283. freeweight-1.0.0rc1/src/freeweight/web/routes/system.py +209 -0
  284. freeweight-1.0.0rc1/src/freeweight/web/routes/wizard.py +594 -0
  285. freeweight-1.0.0rc1/src/freeweight/web/static/js/charts.js +45 -0
  286. freeweight-1.0.0rc1/src/freeweight/web/static/js/dashboard.js +51 -0
  287. freeweight-1.0.0rc1/src/freeweight/web/static/js/runs.js +105 -0
  288. freeweight-1.0.0rc1/src/freeweight/web/static/js/table.js +174 -0
  289. freeweight-1.0.0rc1/src/freeweight/web/static/js/telemetry.js +99 -0
  290. freeweight-1.0.0rc1/src/freeweight/web/templates/base.html +410 -0
  291. freeweight-1.0.0rc1/src/freeweight/web/templates/compare/index.html +248 -0
  292. freeweight-1.0.0rc1/src/freeweight/web/templates/dashboard/index.html +232 -0
  293. freeweight-1.0.0rc1/src/freeweight/web/templates/database/index.html +202 -0
  294. freeweight-1.0.0rc1/src/freeweight/web/templates/evidence/index.html +152 -0
  295. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/grade.html +120 -0
  296. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/index.html +80 -0
  297. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/report.html +164 -0
  298. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/starters.html +108 -0
  299. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/wizard_criteria.html +179 -0
  300. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/wizard_intent.html +34 -0
  301. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/wizard_rules.html +58 -0
  302. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/wizard_save.html +80 -0
  303. freeweight-1.0.0rc1/src/freeweight/web/templates/goals/wizard_tasks.html +71 -0
  304. freeweight-1.0.0rc1/src/freeweight/web/templates/grading/run.html +107 -0
  305. freeweight-1.0.0rc1/src/freeweight/web/templates/machines/index.html +45 -0
  306. freeweight-1.0.0rc1/src/freeweight/web/templates/models/.gitkeep +0 -0
  307. freeweight-1.0.0rc1/src/freeweight/web/templates/models/detail.html +69 -0
  308. freeweight-1.0.0rc1/src/freeweight/web/templates/models/index.html +66 -0
  309. freeweight-1.0.0rc1/src/freeweight/web/templates/partials/_inventory_states.html +22 -0
  310. freeweight-1.0.0rc1/src/freeweight/web/templates/partials/_scatter.html +71 -0
  311. freeweight-1.0.0rc1/src/freeweight/web/templates/partials/_wizard_steps.html +21 -0
  312. freeweight-1.0.0rc1/src/freeweight/web/templates/partials/telemetry_bar.html +50 -0
  313. freeweight-1.0.0rc1/src/freeweight/web/templates/results/case.html +217 -0
  314. freeweight-1.0.0rc1/src/freeweight/web/templates/results/goal_detail.html +135 -0
  315. freeweight-1.0.0rc1/src/freeweight/web/templates/results/index.html +133 -0
  316. freeweight-1.0.0rc1/src/freeweight/web/templates/runs/.gitkeep +0 -0
  317. freeweight-1.0.0rc1/src/freeweight/web/templates/runs/detail.html +244 -0
  318. freeweight-1.0.0rc1/src/freeweight/web/templates/runs/index.html +80 -0
  319. freeweight-1.0.0rc1/src/freeweight/web/templates/runs/samples.html +84 -0
  320. freeweight-1.0.0rc1/src/freeweight/web/templates/settings/index.html +97 -0
  321. freeweight-1.0.0rc1/tests/accessibility/test_ui_checklist.py +384 -0
  322. freeweight-1.0.0rc1/tests/conftest.py +132 -0
  323. freeweight-1.0.0rc1/tests/contract/test_declared_surface.py +108 -0
  324. freeweight-1.0.0rc1/tests/contract/test_evidence_export.py +958 -0
  325. freeweight-1.0.0rc1/tests/contract/test_evidence_schema.py +227 -0
  326. freeweight-1.0.0rc1/tests/contract/test_export_schemas.py +535 -0
  327. freeweight-1.0.0rc1/tests/e2e/test_cli_basics.py +261 -0
  328. freeweight-1.0.0rc1/tests/e2e/test_cli_db.py +190 -0
  329. freeweight-1.0.0rc1/tests/e2e/test_dashboard.py +365 -0
  330. freeweight-1.0.0rc1/tests/e2e/test_declared_endpoints.py +208 -0
  331. freeweight-1.0.0rc1/tests/e2e/test_delete_preview.py +372 -0
  332. freeweight-1.0.0rc1/tests/e2e/test_drilldown.py +318 -0
  333. freeweight-1.0.0rc1/tests/e2e/test_export.py +596 -0
  334. freeweight-1.0.0rc1/tests/e2e/test_full_journeys.py +4 -0
  335. freeweight-1.0.0rc1/tests/e2e/test_goal_wizard_journey.py +586 -0
  336. freeweight-1.0.0rc1/tests/e2e/test_goals_api.py +507 -0
  337. freeweight-1.0.0rc1/tests/e2e/test_grading_resumable.py +369 -0
  338. freeweight-1.0.0rc1/tests/e2e/test_models_flow.py +212 -0
  339. freeweight-1.0.0rc1/tests/e2e/test_pages.py +226 -0
  340. freeweight-1.0.0rc1/tests/e2e/test_run_journey.py +641 -0
  341. freeweight-1.0.0rc1/tests/e2e/test_server_boot.py +167 -0
  342. freeweight-1.0.0rc1/tests/integration/conftest.py +109 -0
  343. freeweight-1.0.0rc1/tests/integration/test_backup_restore.py +439 -0
  344. freeweight-1.0.0rc1/tests/integration/test_calibration_flow.py +860 -0
  345. freeweight-1.0.0rc1/tests/integration/test_goal_run_rules_only.py +509 -0
  346. freeweight-1.0.0rc1/tests/integration/test_human_grading.py +504 -0
  347. freeweight-1.0.0rc1/tests/integration/test_integration_milestones.py +154 -0
  348. freeweight-1.0.0rc1/tests/integration/test_jury_assembly.py +488 -0
  349. freeweight-1.0.0rc1/tests/integration/test_migrations.py +287 -0
  350. freeweight-1.0.0rc1/tests/integration/test_performance_benchmark.py +594 -0
  351. freeweight-1.0.0rc1/tests/integration/test_quality_suites.py +665 -0
  352. freeweight-1.0.0rc1/tests/integration/test_recovery.py +269 -0
  353. freeweight-1.0.0rc1/tests/integration/test_repositories.py +316 -0
  354. freeweight-1.0.0rc1/tests/integration/test_run_execution.py +538 -0
  355. freeweight-1.0.0rc1/tests/integration/test_sandbox_tiers.py +4 -0
  356. freeweight-1.0.0rc1/tests/integration/test_sse_replay.py +332 -0
  357. freeweight-1.0.0rc1/tests/integration/test_starter_packs.py +423 -0
  358. freeweight-1.0.0rc1/tests/integration/test_telemetry_sse.py +222 -0
  359. freeweight-1.0.0rc1/tests/integration/test_transactions.py +94 -0
  360. freeweight-1.0.0rc1/tests/integration/test_two_phase_judging.py +372 -0
  361. freeweight-1.0.0rc1/tests/live/test_real_run.py +1074 -0
  362. freeweight-1.0.0rc1/tests/performance/test_dashboard_queries.py +416 -0
  363. freeweight-1.0.0rc1/tests/security/test_goal_pack_import.py +365 -0
  364. freeweight-1.0.0rc1/tests/security/test_mock_tools_contained.py +468 -0
  365. freeweight-1.0.0rc1/tests/security/test_sandbox_refusal.py +4 -0
  366. freeweight-1.0.0rc1/tests/security/test_settings_boundary.py +211 -0
  367. freeweight-1.0.0rc1/tests/unit/test_aggregation.py +353 -0
  368. freeweight-1.0.0rc1/tests/unit/test_agreement.py +222 -0
  369. freeweight-1.0.0rc1/tests/unit/test_audit_metrics.py +229 -0
  370. freeweight-1.0.0rc1/tests/unit/test_bootstrap.py +36 -0
  371. freeweight-1.0.0rc1/tests/unit/test_capability_mapping.py +244 -0
  372. freeweight-1.0.0rc1/tests/unit/test_comparison_rules.py +277 -0
  373. freeweight-1.0.0rc1/tests/unit/test_composite.py +267 -0
  374. freeweight-1.0.0rc1/tests/unit/test_confidence.py +366 -0
  375. freeweight-1.0.0rc1/tests/unit/test_config.py +255 -0
  376. freeweight-1.0.0rc1/tests/unit/test_context_sweep.py +200 -0
  377. freeweight-1.0.0rc1/tests/unit/test_critique_metrics.py +243 -0
  378. freeweight-1.0.0rc1/tests/unit/test_database_admin.py +52 -0
  379. freeweight-1.0.0rc1/tests/unit/test_db_types.py +164 -0
  380. freeweight-1.0.0rc1/tests/unit/test_effective_context.py +351 -0
  381. freeweight-1.0.0rc1/tests/unit/test_energy_integration.py +226 -0
  382. freeweight-1.0.0rc1/tests/unit/test_event_sequence.py +297 -0
  383. freeweight-1.0.0rc1/tests/unit/test_external_output_parsing.py +4 -0
  384. freeweight-1.0.0rc1/tests/unit/test_gate.py +164 -0
  385. freeweight-1.0.0rc1/tests/unit/test_goal_hash.py +225 -0
  386. freeweight-1.0.0rc1/tests/unit/test_goal_lint.py +492 -0
  387. freeweight-1.0.0rc1/tests/unit/test_judge_bias.py +511 -0
  388. freeweight-1.0.0rc1/tests/unit/test_kappa_weighted.py +225 -0
  389. freeweight-1.0.0rc1/tests/unit/test_krippendorff.py +102 -0
  390. freeweight-1.0.0rc1/tests/unit/test_kv_math.py +381 -0
  391. freeweight-1.0.0rc1/tests/unit/test_logging.py +154 -0
  392. freeweight-1.0.0rc1/tests/unit/test_machine_profile.py +120 -0
  393. freeweight-1.0.0rc1/tests/unit/test_metric_formulas.py +224 -0
  394. freeweight-1.0.0rc1/tests/unit/test_model_discovery.py +386 -0
  395. freeweight-1.0.0rc1/tests/unit/test_partition.py +119 -0
  396. freeweight-1.0.0rc1/tests/unit/test_prompt_pack.py +625 -0
  397. freeweight-1.0.0rc1/tests/unit/test_provenance.py +301 -0
  398. freeweight-1.0.0rc1/tests/unit/test_provider_factory.py +58 -0
  399. freeweight-1.0.0rc1/tests/unit/test_rules_length.py +163 -0
  400. freeweight-1.0.0rc1/tests/unit/test_rules_phrases.py +104 -0
  401. freeweight-1.0.0rc1/tests/unit/test_rules_pov_tense.py +85 -0
  402. freeweight-1.0.0rc1/tests/unit/test_rules_punctuation.py +72 -0
  403. freeweight-1.0.0rc1/tests/unit/test_rules_readability.py +109 -0
  404. freeweight-1.0.0rc1/tests/unit/test_rules_reference.py +220 -0
  405. freeweight-1.0.0rc1/tests/unit/test_rules_regex.py +116 -0
  406. freeweight-1.0.0rc1/tests/unit/test_rules_repetition.py +70 -0
  407. freeweight-1.0.0rc1/tests/unit/test_rules_structure.py +118 -0
  408. freeweight-1.0.0rc1/tests/unit/test_rules_vocabulary.py +84 -0
  409. freeweight-1.0.0rc1/tests/unit/test_run_state_machine.py +181 -0
  410. freeweight-1.0.0rc1/tests/unit/test_runtime_profile.py +172 -0
  411. freeweight-1.0.0rc1/tests/unit/test_scheduler.py +232 -0
  412. freeweight-1.0.0rc1/tests/unit/test_scorers_agent.py +211 -0
  413. freeweight-1.0.0rc1/tests/unit/test_scorers_exact.py +103 -0
  414. freeweight-1.0.0rc1/tests/unit/test_scorers_rule.py +174 -0
  415. freeweight-1.0.0rc1/tests/unit/test_scorers_schema.py +141 -0
  416. freeweight-1.0.0rc1/tests/unit/test_scorers_tools.py +288 -0
  417. freeweight-1.0.0rc1/tests/unit/test_statistics.py +310 -0
  418. freeweight-1.0.0rc1/tests/unit/test_sweep_ladder.py +98 -0
  419. freeweight-1.0.0rc1/tests/unit/test_telemetry_service.py +221 -0
  420. freeweight-1.0.0rc1/tests/unit/test_validity_factor.py +146 -0
  421. freeweight-1.0.0rc1/tests/unit/test_web_errors.py +87 -0
@@ -0,0 +1,23 @@
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
+ [*.py]
12
+ indent_size = 4
13
+ max_line_length = 100
14
+
15
+ [*.{toml,yml,yaml,json}]
16
+ indent_size = 2
17
+
18
+ [*.md]
19
+ trim_trailing_whitespace = false
20
+ max_line_length = off
21
+
22
+ [Makefile]
23
+ indent_style = tab
@@ -0,0 +1,199 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ format:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with: { python-version: "3.12" }
15
+ - run: pip install ruff
16
+ - run: ruff format --check .
17
+
18
+ lint:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: actions/setup-python@v5
23
+ with: { python-version: "3.12" }
24
+ - run: pip install ruff
25
+ - run: ruff check .
26
+
27
+ types:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ - uses: actions/setup-python@v5
32
+ with: { python-version: "3.12" }
33
+ - run: pip install -e ".[dev]"
34
+ - run: mypy src tests
35
+
36
+ boundaries:
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ - uses: actions/setup-python@v5
41
+ with: { python-version: "3.12" }
42
+ - run: pip install -e ".[dev]"
43
+ - run: lint-imports
44
+
45
+ tests:
46
+ runs-on: ubuntu-latest
47
+ strategy:
48
+ matrix:
49
+ python-version: ["3.12", "3.13"]
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: actions/setup-python@v5
53
+ with: { python-version: "${{ matrix.python-version }}" }
54
+ - run: pip install -e ".[dev]"
55
+ - run: pytest -m "not live and not performance" --cov --cov-report=xml
56
+
57
+ postgresql-tests:
58
+ # Database standards §5.2: the migration suite runs on both supported dialects in CI, not
59
+ # just SQLite. FREEWEIGHT_REQUIRE_POSTGRES turns tests/integration/conftest.py's ordinary
60
+ # "skip if unreachable" behaviour into a failure here, so a broken service container fails
61
+ # the job instead of silently testing one dialect and calling it both.
62
+ runs-on: ubuntu-latest
63
+ services:
64
+ postgres:
65
+ image: postgres:16
66
+ env:
67
+ POSTGRES_USER: freeweight
68
+ POSTGRES_PASSWORD: freeweight
69
+ POSTGRES_DB: freeweight_test
70
+ ports: ["5432:5432"]
71
+ options: >-
72
+ --health-cmd pg_isready
73
+ --health-interval 10s
74
+ --health-timeout 5s
75
+ --health-retries 5
76
+ env:
77
+ # Deliberately not the FREEWEIGHT_ prefix: tests/conftest.py strips those so no test reads
78
+ # the developer's environment, which would delete these before the fixture could read them.
79
+ FWTEST_REQUIRE_POSTGRES: "1"
80
+ FWTEST_POSTGRES_URL: postgresql+psycopg://freeweight:freeweight@localhost:5432/freeweight_test
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+ - uses: actions/setup-python@v5
84
+ with: { python-version: "3.12" }
85
+ # pg_dump is what `freeweight db backup` shells out to on this dialect; without the client
86
+ # tools that branch skips itself and the job reports green having never run it.
87
+ - run: sudo apt-get update && sudo apt-get install -y postgresql-client
88
+ - run: pip install -e ".[dev]"
89
+ - run: pytest -m "not live and not performance" tests/integration
90
+
91
+ tests-314-early-warning:
92
+ runs-on: ubuntu-latest
93
+ continue-on-error: true
94
+ steps:
95
+ - uses: actions/checkout@v4
96
+ - uses: actions/setup-python@v5
97
+ with: { python-version: "3.14" }
98
+ - run: pip install -e ".[dev]"
99
+ - run: pytest -m "not live and not performance"
100
+
101
+ coverage:
102
+ needs: [tests]
103
+ runs-on: ubuntu-latest
104
+ steps:
105
+ - uses: actions/checkout@v4
106
+ - uses: actions/setup-python@v5
107
+ with: { python-version: "3.12" }
108
+ - run: pip install -e ".[dev]"
109
+ - run: pytest -m "not live and not performance" --cov --cov-report=term-missing --cov-fail-under=85
110
+
111
+ diff-coverage:
112
+ # Testing standards §10 lists `diff-cover` among the gates required before merge: the
113
+ # repository-wide floor says nothing about whether *this change* was tested, and a large
114
+ # well-covered codebase absorbs an untested addition without the floor moving.
115
+ needs: [tests]
116
+ runs-on: ubuntu-latest
117
+ if: github.event_name == 'pull_request'
118
+ steps:
119
+ - uses: actions/checkout@v4
120
+ # diff-cover compares against the merge base, so the base branch has to be in the object
121
+ # store; a depth-1 clone does not have it.
122
+ with: { fetch-depth: 0 }
123
+ - uses: actions/setup-python@v5
124
+ with: { python-version: "3.12" }
125
+ - run: pip install -e ".[dev]"
126
+ - run: pytest -m "not live and not performance" --cov --cov-report=xml
127
+ - run: diff-cover coverage.xml --compare-branch=origin/${{ github.base_ref }} --fail-under=90
128
+
129
+ contracts:
130
+ runs-on: ubuntu-latest
131
+ steps:
132
+ - uses: actions/checkout@v4
133
+ - uses: actions/setup-python@v5
134
+ with: { python-version: "3.12" }
135
+ - run: pip install -e ".[dev]"
136
+ - run: pytest -m contract
137
+
138
+ docs:
139
+ # Packaging standards §5's `docs` job: the generated documents must match what the code
140
+ # generates. `docs/configuration.md` is produced from the settings model (configuration
141
+ # standards §8) and `docs/openapi.json` from the served application (API standards §11); a
142
+ # field or a route changed without regenerating either fails here rather than drifting.
143
+ runs-on: ubuntu-latest
144
+ steps:
145
+ - uses: actions/checkout@v4
146
+ - uses: actions/setup-python@v5
147
+ with: { python-version: "3.12" }
148
+ - run: pip install -e ".[dev]"
149
+ - run: python scripts/generate_config_reference.py --check
150
+ - run: python scripts/generate_openapi_snapshot.py --check
151
+
152
+ security:
153
+ # `pip-audit` audits the locked set, not the job's own environment: a bare `pip-audit` here
154
+ # inspects an environment containing only pip-audit itself and reports nothing (Security
155
+ # Standards §11). It audits `requirements/ci.lock` too once that file exists — it is blocked
156
+ # on `setspec 0.3.0` reaching PyPI, for the reason requirements/README.md gives.
157
+ runs-on: ubuntu-latest
158
+ steps:
159
+ - uses: actions/checkout@v4
160
+ # gitleaks scans *history*, and `actions/checkout` fetches a single commit by default.
161
+ # For a push it is handed `<first-pushed>^..<last-pushed>`, so the parent of the first
162
+ # pushed commit has to be in the object store; in a depth-1 clone it is not, and git
163
+ # answers "unknown revision", which the action reports as exit code 1. It fails the same
164
+ # way whether or not a secret exists, so a green run would not have meant anything either.
165
+ with: { fetch-depth: 0 }
166
+ - uses: actions/setup-python@v5
167
+ with: { python-version: "3.12" }
168
+ - run: pip install pip-audit
169
+ - run: pip-audit --require-hashes -r requirements/release.lock
170
+ - uses: gitleaks/gitleaks-action@v2
171
+ env:
172
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
173
+
174
+ build:
175
+ runs-on: ubuntu-latest
176
+ steps:
177
+ - uses: actions/checkout@v4
178
+ - uses: actions/setup-python@v5
179
+ with: { python-version: "3.12" }
180
+ # The same pinned build chain the release uses, so a wheel that builds here is the wheel
181
+ # that ships: `--no-isolation` takes the backend from this lock rather than re-resolving
182
+ # hatchling from the index at build time (requirements/README.md).
183
+ - run: pip install --require-hashes -r requirements/release.lock
184
+ - run: python -m build --no-isolation
185
+ - run: twine check dist/*
186
+ - uses: actions/upload-artifact@v4
187
+ with: { name: dist, path: dist/ }
188
+
189
+ install-check:
190
+ needs: [build]
191
+ runs-on: ubuntu-latest
192
+ steps:
193
+ - uses: actions/checkout@v4
194
+ - uses: actions/setup-python@v5
195
+ with: { python-version: "3.12" }
196
+ - uses: actions/download-artifact@v4
197
+ with: { name: dist, path: dist/ }
198
+ - run: pip install dist/*.whl
199
+ - run: python -c "import freeweight"
@@ -0,0 +1,41 @@
1
+ # Testing Standards §10: the default suite runs on every push and must stay under three minutes,
2
+ # so the two suites that cannot be fast run here instead — `live` needs real weights and `performance`
3
+ # needs a machine whose timings mean something.
4
+ #
5
+ # On a GitHub-hosted runner the live suite **skips itself**: its provider fixture calls
6
+ # `OllamaProvider.health()` and skips when nothing answers on 127.0.0.1:11434. That is deliberate
7
+ # and is not a silent pass — the job prints the skip reasons with `-rs`, so "no Ollama here" is
8
+ # visible rather than indistinguishable from "everything passed". Point a self-hosted runner with a
9
+ # GPU at this workflow and the same job measures a real model.
10
+ #
11
+ # `performance` runs everywhere: its budgets are generous precisely so that shared CI hardware
12
+ # produces information rather than flakes, and the query-plan assertions beside them are
13
+ # hardware-independent.
14
+ name: Nightly
15
+
16
+ on:
17
+ schedule:
18
+ # 03:00 UTC — after any working day's pushes, before any working morning.
19
+ - cron: "0 3 * * *"
20
+ workflow_dispatch:
21
+
22
+ jobs:
23
+ performance:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: actions/setup-python@v5
28
+ with: { python-version: "3.12" }
29
+ - run: pip install -e ".[dev]"
30
+ - run: pytest -m performance -rs
31
+
32
+ live:
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ - uses: actions/setup-python@v5
37
+ with: { python-version: "3.12" }
38
+ - run: pip install -e ".[dev]"
39
+ # `-rs` reports every skip with its reason: a live suite that skipped because nothing was
40
+ # serving must not look like a live suite that passed.
41
+ - run: pytest -m live -rs
@@ -0,0 +1,58 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*.*.*"]
6
+ workflow_dispatch: # manual TestPyPI dry run; see publish-testpypi below
7
+
8
+ permissions:
9
+ id-token: write # required for PyPI Trusted Publishing
10
+ contents: write # required to create the GitHub release
11
+
12
+ jobs:
13
+ release:
14
+ if: github.event_name == 'push'
15
+ runs-on: ubuntu-latest
16
+ environment: pypi # must match the Environment name set on the PyPI trusted publisher
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with: { python-version: "3.12" }
21
+ # The pinned build chain, so the wheel that ships is built by the same backend CI checked:
22
+ # `--no-isolation` takes hatchling from this lock rather than re-resolving it at build time.
23
+ - run: pip install --require-hashes -r requirements/release.lock
24
+ - run: python -m build --no-isolation
25
+ - run: twine check dist/*
26
+ - run: pip install "dist/$(ls dist | grep .whl)[dev]"
27
+ - run: pytest -m "not live and not performance"
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
30
+ - name: Create GitHub release
31
+ uses: softprops/action-gh-release@v2
32
+ with:
33
+ generate_release_notes: true
34
+ files: dist/*
35
+
36
+ publish-testpypi:
37
+ # Manual only, via Actions -> Release -> Run workflow. Packaging and Release Standards §6
38
+ # requires a successful TestPyPI publish ahead of a package's **first** real release, and
39
+ # `freeweight` is an unclaimed distribution name — v1.0.0rc1 is that first release, so run
40
+ # this once before tagging it. Later releases may skip it, or use it again as a dry run.
41
+ if: github.event_name == 'workflow_dispatch'
42
+ runs-on: ubuntu-latest
43
+ # No `environment:` here, matching the package repositories. The OIDC claim must match the
44
+ # trusted publisher exactly: declaring an environment the TestPyPI publisher was not
45
+ # configured with fails the exchange. Add one only alongside configuring it there.
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ - uses: actions/setup-python@v5
49
+ with: { python-version: "3.12" }
50
+ - run: pip install --require-hashes -r requirements/release.lock
51
+ - run: python -m build --no-isolation
52
+ - run: twine check dist/*
53
+ - run: pip install "dist/$(ls dist | grep .whl)[dev]"
54
+ - run: pytest -m "not live and not performance"
55
+ - name: Publish to TestPyPI
56
+ uses: pypa/gh-action-pypi-publish@release/v1
57
+ with:
58
+ repository-url: https://test.pypi.org/legacy/
@@ -0,0 +1,100 @@
1
+ # ---- Python ----
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # ---- Packaging / build backends ----
25
+ pip-wheel-metadata/
26
+ share/python-wheels/
27
+
28
+ # ---- Testing / coverage ----
29
+ .pytest_cache/
30
+ .cache
31
+ .coverage
32
+ .coverage.*
33
+ coverage.xml
34
+ *.cover
35
+ *.py,cover
36
+ htmlcov/
37
+ nosetests.xml
38
+ .hypothesis/
39
+
40
+ # ---- Type checking / linting ----
41
+ .mypy_cache/
42
+ .dmypy.json
43
+ dmypy.json
44
+ .ruff_cache/
45
+ .pytype/
46
+
47
+ # ---- Virtual environments ----
48
+ .venv/
49
+ venv/
50
+ ENV/
51
+ env/
52
+ env.bak/
53
+ venv.bak/
54
+ .python-version
55
+
56
+ # ---- Distribution / dependency locking ----
57
+ # requirements/*.lock is deliberately NOT ignored. The lock files are committed
58
+ # inputs: CI and release jobs install from them with --require-hashes (Packaging
59
+ # and Release Standards §4, Security Standards §11), so an ignored lock file
60
+ # means a checkout that cannot build.
61
+
62
+ # ---- Editors / OS ----
63
+ .vscode/
64
+ .idea/
65
+ *.swp
66
+ *.swo
67
+ .DS_Store
68
+ Thumbs.db
69
+
70
+ # ---- Suite runtime state (this component's local data) ----
71
+ # The application writes to XDG paths at runtime (~/.config, ~/.local/share,
72
+ # ~/.local/state per Master Architecture §1.2), never inside the repository.
73
+ # These entries only guard against a developer pointing XDG_* at the repo
74
+ # during local testing.
75
+ .local/
76
+ .config/
77
+ *.sqlite3
78
+ *.sqlite3-journal
79
+ *.sqlite3-wal
80
+ *.sqlite3-shm
81
+ /data/
82
+ /logs/
83
+ /backups/
84
+ /artifacts/
85
+ /exports/
86
+
87
+ # ---- Secrets ----
88
+ # Per Security Standards §8: secrets are never committed. Config files may
89
+ # only name where a secret comes from (*_env / *_file), never the value.
90
+ .env
91
+ .env.*
92
+ *.key
93
+ *.pem
94
+ secrets.toml
95
+
96
+ # ---- Node-free JS assets (MirrorWall consumers may still use a local tool) ----
97
+ node_modules/
98
+
99
+ # ---- Build artifacts from docs generation ----
100
+ docs/api/openapi-v1.json.tmp
@@ -0,0 +1,38 @@
1
+ # gitleaks configuration — see the `security` job in .github/workflows/ci.yml.
2
+ #
3
+ # The default rule set is kept in full. This file adds one allowlist and disables nothing: a rule
4
+ # is never turned off, and a finding is never allowlisted by fingerprint, because a fingerprint
5
+ # carries the commit SHA and stops matching the moment the file moves — which turns "a person
6
+ # looked at this and it is not a secret" into a silently unscanned line later.
7
+
8
+ title = "FreeWeight"
9
+
10
+ [extend]
11
+ useDefault = true
12
+
13
+ [allowlist]
14
+ description = "A metric key is vocabulary, not a credential."
15
+ # `generic-api-key` fires on any `…key = <high-entropy value>` assignment, and this suite names
16
+ # every measurement with a `metric_key` — 129 of them across 51 files, and one per new benchmark.
17
+ # `inter_chunk_ms_p50` and `inter_chunk_ms_p95` clear the rule's entropy floor, so they are
18
+ # reported as secrets; the rest are one lucky character away from joining them, which is why this
19
+ # matches the *shape* of a metric key rather than listing the two names that happen to trip it
20
+ # today.
21
+ #
22
+ # The scan is diff-scoped, so this fails only on a push whose commit touches one of those lines —
23
+ # it has fired three times (a2a0ac5, 92f5602, e6d3c88, the last on the `key` → `metric_key`
24
+ # rename) and passed on every commit that leaves them alone. A green run on an unrelated commit is
25
+ # not evidence that it is fixed.
26
+ #
27
+ # What this permits is narrow: a `…key` field bound to a lowercase snake_case identifier, quoted
28
+ # and ending the match. A real credential is excluded by any of the things it almost always has
29
+ # and an identifier never does — an uppercase letter, a hyphen, a dot, a `+` or `/`, or no
30
+ # underscore at all. Keywords other than `key` are untouched, so `password = "correct_horse_..."`
31
+ # is still a finding.
32
+ #
33
+ # `regexTarget` must be `match`: in a history scan — the mode CI runs in — a finding's `line` is
34
+ # empty, so an allowlist written against the source line matches nothing and silently does not
35
+ # apply. The match text differs between the two modes as well (`metric_key="…"` scanning a working
36
+ # tree, `key="…"` scanning a diff), so the pattern deliberately starts at `key`.
37
+ regexTarget = "match"
38
+ regexes = ['''key["']?\s*[:=]\s*["'][a-z][a-z0-9]*(?:_[a-z0-9]+)+["']$''']
@@ -0,0 +1,40 @@
1
+ [importlinter]
2
+ root_package = freeweight
3
+ include_external_packages = True
4
+
5
+ [importlinter:contract:layers]
6
+ name = FreeWeight internal layering
7
+ type = layers
8
+ layers =
9
+ web
10
+ cli
11
+ services
12
+ domain
13
+ containers = freeweight
14
+
15
+ [importlinter:contract:web-cli-independence]
16
+ name = Web and CLI never import each other
17
+ type = independence
18
+ modules =
19
+ freeweight.web
20
+ freeweight.cli
21
+
22
+ [importlinter:contract:domain-purity]
23
+ name = Domain imports no frameworks
24
+ type = forbidden
25
+ source_modules = freeweight.domain
26
+ forbidden_modules =
27
+ fastapi
28
+ starlette
29
+ sqlalchemy
30
+ typer
31
+ httpx
32
+ jinja2
33
+
34
+ [importlinter:contract:no-other-applications]
35
+ name = FreeWeight must not import other applications
36
+ type = forbidden
37
+ source_modules = freeweight
38
+ forbidden_modules =
39
+ loadcoach
40
+ ideapress
@@ -0,0 +1,22 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+ - repo: https://github.com/pre-commit/pre-commit-hooks
9
+ rev: v4.6.0
10
+ hooks:
11
+ - id: trailing-whitespace
12
+ - id: end-of-file-fixer
13
+ - id: check-toml
14
+ - id: check-json
15
+ - id: check-added-large-files
16
+ - id: check-merge-conflict
17
+ - id: mixed-line-ending
18
+ args: [--fix=lf]
19
+ - repo: https://github.com/gitleaks/gitleaks
20
+ rev: v8.18.4
21
+ hooks:
22
+ - id: gitleaks