flexlock 0.8.2__tar.gz → 0.10.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 (318) hide show
  1. flexlock-0.10.0/.github/scripts/check_public_docs.py +16 -0
  2. flexlock-0.10.0/.github/scripts/check_version.py +35 -0
  3. flexlock-0.10.0/.github/workflows/ci.yml +66 -0
  4. flexlock-0.10.0/.github/workflows/docs.yml +58 -0
  5. flexlock-0.10.0/.github/workflows/release.yml +93 -0
  6. {flexlock-0.8.2 → flexlock-0.10.0}/.gitignore +3 -0
  7. flexlock-0.10.0/CHANGELOG.md +78 -0
  8. flexlock-0.10.0/PKG-INFO +120 -0
  9. flexlock-0.10.0/README.md +105 -0
  10. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/agentic_workflows.md +9 -9
  11. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/api.rst +5 -0
  12. flexlock-0.10.0/docs/changelog.md +2 -0
  13. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/cli_reference.md +207 -15
  14. flexlock-0.10.0/docs/dev_plan_pipeline_tasks.md +258 -0
  15. flexlock-0.10.0/docs/dev_plan_presets_records.md +408 -0
  16. flexlock-0.10.0/docs/dev_plan_workflow_integrity.md +61 -0
  17. {flexlock-0.8.2 → flexlock-0.10.0}/docs/hpc_integration.md +264 -107
  18. flexlock-0.10.0/docs/index.rst +72 -0
  19. flexlock-0.10.0/docs/next_migration_decisions.md +123 -0
  20. flexlock-0.10.0/docs/optional_policy_inventory.md +166 -0
  21. flexlock-0.10.0/docs/performance_core_followup.md +413 -0
  22. flexlock-0.10.0/docs/philosophy.md +64 -0
  23. flexlock-0.10.0/docs/project_adoption_handoff.md +112 -0
  24. flexlock-0.10.0/docs/project_feedback_followup.md +103 -0
  25. flexlock-0.10.0/docs/project_feedback_triage.md +44 -0
  26. flexlock-0.10.0/docs/project_instructions.md +24 -0
  27. flexlock-0.10.0/docs/project_migration_agents.md +33 -0
  28. flexlock-0.10.0/docs/project_registry_items.md +97 -0
  29. flexlock-0.10.0/docs/provenance_discovery_decision.md +75 -0
  30. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/python_api.md +82 -219
  31. {flexlock-0.8.2 → flexlock-0.10.0}/docs/quickstart.md +11 -15
  32. flexlock-0.10.0/docs/record_and_source_scope_migration.md +70 -0
  33. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/reference.md +14 -39
  34. flexlock-0.10.0/docs/release_0_10.md +73 -0
  35. flexlock-0.10.0/docs/release_0_10_0rc1.md +3 -0
  36. flexlock-0.10.0/docs/release_0_9_1.md +64 -0
  37. flexlock-0.10.0/docs/release_0_9_2.md +36 -0
  38. flexlock-0.10.0/docs/release_0_9_3.md +31 -0
  39. {flexlock-0.8.2 → flexlock-0.10.0}/docs/resolution_simplification_plan.md +6 -0
  40. {flexlock-0.8.2 → flexlock-0.10.0}/docs/resolvers.md +52 -12
  41. flexlock-0.10.0/docs/slimmer_core_migration.md +381 -0
  42. flexlock-0.10.0/docs/slurm_submission_workflow.md +118 -0
  43. flexlock-0.10.0/docs/source_attribution.md +95 -0
  44. flexlock-0.10.0/docs/urgent_fix_decisions.md +44 -0
  45. {flexlock-0.8.2 → flexlock-0.10.0}/docs/usage_guide.md +265 -115
  46. flexlock-0.10.0/docs/workflow_guidelines.md +481 -0
  47. flexlock-0.10.0/docs/workflow_lifecycle.md +67 -0
  48. flexlock-0.10.0/examples/slimmer_workflows/README.md +22 -0
  49. flexlock-0.10.0/examples/slimmer_workflows/bindings.py +45 -0
  50. flexlock-0.10.0/examples/slimmer_workflows/campaign.py +109 -0
  51. flexlock-0.10.0/examples/slimmer_workflows/cfgmod.py +32 -0
  52. flexlock-0.10.0/examples/slimmer_workflows/chunk_coverage.py +53 -0
  53. flexlock-0.10.0/examples/slimmer_workflows/orchestrate.py +46 -0
  54. flexlock-0.10.0/examples/slimmer_workflows/sar_coverage.py +105 -0
  55. flexlock-0.10.0/examples/slimmer_workflows/slurm/cpu-pool.yaml +9 -0
  56. flexlock-0.10.0/examples/slimmer_workflows/slurm/cpu.yaml +8 -0
  57. flexlock-0.10.0/examples/slimmer_workflows/slurm/gpu.yaml +9 -0
  58. flexlock-0.10.0/examples/slimmer_workflows/stages.py +42 -0
  59. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/__init__.py +2 -2
  60. flexlock-0.10.0/flexlock/api.py +1625 -0
  61. flexlock-0.10.0/flexlock/backends/dependencies.py +31 -0
  62. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/backends/pbs.py +18 -0
  63. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/backends/slurm.py +79 -14
  64. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/cli.py +264 -17
  65. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/config.py +37 -3
  66. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/data_hash.py +10 -80
  67. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/debug.py +12 -5
  68. flexlock-0.10.0/flexlock/destination_guard.py +249 -0
  69. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/diff.py +85 -10
  70. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/diff_cli.py +40 -13
  71. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/exceptions.py +5 -1
  72. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/export.py +5 -0
  73. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/fingerprint.py +83 -5
  74. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/freeze.py +35 -2
  75. flexlock-0.10.0/flexlock/git_utils.py +292 -0
  76. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/index.py +81 -48
  77. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/load_stage.py +19 -13
  78. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/mlflow.py +11 -11
  79. flexlock-0.10.0/flexlock/outputs.py +112 -0
  80. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/parallel.py +164 -8
  81. flexlock-0.10.0/flexlock/presets.py +575 -0
  82. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/query.py +45 -60
  83. flexlock-0.10.0/flexlock/queue_refs.py +72 -0
  84. flexlock-0.10.0/flexlock/record.py +265 -0
  85. flexlock-0.10.0/flexlock/registry.py +64 -0
  86. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/report_template.html +6 -0
  87. flexlock-0.10.0/flexlock/resolvers.py +437 -0
  88. flexlock-0.10.0/flexlock/run_record.py +327 -0
  89. flexlock-0.10.0/flexlock/runner.py +999 -0
  90. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/save_dir.py +11 -6
  91. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/skills/flexlock-new-stage/SKILL.md +10 -4
  92. flexlock-0.10.0/flexlock/skills/flexlock-run-and-watch/SKILL.md +63 -0
  93. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/skills/flexlock-survey/SKILL.md +12 -1
  94. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/snapshot.py +134 -15
  95. flexlock-0.10.0/flexlock/sweep_compile.py +109 -0
  96. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/taskdb.py +67 -6
  97. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/utils.py +335 -46
  98. flexlock-0.10.0/flexlock/worker.py +484 -0
  99. {flexlock-0.8.2 → flexlock-0.10.0}/flexlock/worker_cli.py +7 -0
  100. {flexlock-0.8.2 → flexlock-0.10.0}/pyproject.toml +6 -3
  101. flexlock-0.10.0/tests/registry_items_acceptance.py +60 -0
  102. flexlock-0.10.0/tests/slurm_failure_acceptance.py +93 -0
  103. flexlock-0.10.0/tests/test_adoption_diagnostics.py +139 -0
  104. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_api.py +22 -48
  105. flexlock-0.10.0/tests/test_chained_and_paths.py +120 -0
  106. flexlock-0.10.0/tests/test_chunk_coverage_example.py +44 -0
  107. flexlock-0.10.0/tests/test_code_drift.py +197 -0
  108. flexlock-0.10.0/tests/test_compiled_guard_reuse.py +93 -0
  109. flexlock-0.10.0/tests/test_completed_stage_binding.py +55 -0
  110. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_completion_marker.py +2 -35
  111. flexlock-0.10.0/tests/test_controller_lock_handles.py +74 -0
  112. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_data_hash.py +46 -46
  113. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_debug_enhanced.py +18 -0
  114. flexlock-0.10.0/tests/test_destination_guard.py +190 -0
  115. flexlock-0.10.0/tests/test_destination_resolution.py +63 -0
  116. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_diff_cli.py +10 -0
  117. flexlock-0.10.0/tests/test_discovery_policy.py +170 -0
  118. flexlock-0.10.0/tests/test_fingerprint.py +223 -0
  119. flexlock-0.10.0/tests/test_freeze_binding_reuse.py +72 -0
  120. flexlock-0.10.0/tests/test_hpc_dependencies.py +164 -0
  121. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_index.py +10 -46
  122. flexlock-0.10.0/tests/test_lineage_identity.py +39 -0
  123. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_multistage_config.py +80 -3
  124. flexlock-0.10.0/tests/test_ownership_loader.py +79 -0
  125. flexlock-0.10.0/tests/test_ownership_row_cache.py +98 -0
  126. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_parallel.py +19 -19
  127. flexlock-0.10.0/tests/test_pipeline_tasks.py +527 -0
  128. flexlock-0.10.0/tests/test_preparation_io.py +113 -0
  129. flexlock-0.10.0/tests/test_preparation_reuse.py +61 -0
  130. flexlock-0.10.0/tests/test_presets.py +419 -0
  131. flexlock-0.10.0/tests/test_queue_layout.py +63 -0
  132. flexlock-0.10.0/tests/test_queue_record_selection.py +76 -0
  133. flexlock-0.10.0/tests/test_queue_refs.py +129 -0
  134. flexlock-0.10.0/tests/test_record_results.py +65 -0
  135. flexlock-0.10.0/tests/test_registry_items.py +235 -0
  136. flexlock-0.10.0/tests/test_repo_collection_grouping.py +65 -0
  137. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_resolvers.py +13 -3
  138. flexlock-0.10.0/tests/test_reviewed_record_contracts.py +105 -0
  139. flexlock-0.10.0/tests/test_root_anchor_sweep.py +175 -0
  140. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_run_record.py +1 -1
  141. flexlock-0.10.0/tests/test_sar_coverage.py +95 -0
  142. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_save_dir_guard.py +28 -39
  143. flexlock-0.10.0/tests/test_single_task_runlock.py +278 -0
  144. flexlock-0.10.0/tests/test_slim_candidate.py +146 -0
  145. flexlock-0.10.0/tests/test_slimmer_workflow_examples.py +210 -0
  146. flexlock-0.10.0/tests/test_slurm_materialization.py +48 -0
  147. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_slurm_validation.py +13 -0
  148. flexlock-0.10.0/tests/test_source_attribution.py +132 -0
  149. flexlock-0.10.0/tests/test_source_capture_scope.py +59 -0
  150. flexlock-0.10.0/tests/test_submit_bindings.py +249 -0
  151. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_submit_params.py +12 -13
  152. flexlock-0.10.0/tests/test_swaps.py +127 -0
  153. flexlock-0.10.0/tests/test_sweep_compile.py +120 -0
  154. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_sweep_semantics.py +7 -7
  155. flexlock-0.10.0/tests/test_task_export_deferred.py +24 -0
  156. flexlock-0.10.0/tests/test_task_records.py +261 -0
  157. flexlock-0.10.0/tests/test_workflow_adoption_recipe.py +52 -0
  158. flexlock-0.10.0/tests/test_workflow_integrity.py +209 -0
  159. flexlock-0.8.2/.claude/settings.local.json +0 -7
  160. flexlock-0.8.2/.claude/worktrees/dedup-deps/.claude/settings.local.json +0 -7
  161. flexlock-0.8.2/.claude/worktrees/dedup-deps/.gitattributes +0 -2
  162. flexlock-0.8.2/.claude/worktrees/dedup-deps/.gitignore +0 -16
  163. flexlock-0.8.2/.claude/worktrees/dedup-deps/FABLE_IMPLEMENTATION_PLAN.md +0 -368
  164. flexlock-0.8.2/.claude/worktrees/dedup-deps/README.md +0 -341
  165. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/debugging.md +0 -352
  166. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/hpc_integration.md +0 -712
  167. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/index.rst +0 -40
  168. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/philosophy.md +0 -171
  169. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/quickstart.md +0 -175
  170. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/resolution_simplification_plan.md +0 -226
  171. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/resolvers.md +0 -445
  172. flexlock-0.8.2/.claude/worktrees/dedup-deps/docs/usage_guide.md +0 -1075
  173. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/__init__.py +0 -87
  174. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/api.py +0 -1362
  175. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/backends/pbs.py +0 -219
  176. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/backends/slurm.py +0 -333
  177. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/cli.py +0 -953
  178. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/config.py +0 -107
  179. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/data_hash.py +0 -310
  180. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/debug.py +0 -473
  181. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/fingerprint.py +0 -129
  182. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/freeze.py +0 -291
  183. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/git_utils.py +0 -196
  184. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/index.py +0 -300
  185. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/load_stage.py +0 -60
  186. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/query.py +0 -739
  187. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/resolvers.py +0 -248
  188. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/run_record.py +0 -173
  189. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/runner.py +0 -560
  190. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/save_dir.py +0 -124
  191. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/skills/flexlock-new-stage/SKILL.md +0 -56
  192. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/skills/flexlock-run-and-watch/SKILL.md +0 -58
  193. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/skills/flexlock-survey/SKILL.md +0 -61
  194. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/taskdb.py +0 -589
  195. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/utils.py +0 -710
  196. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/worker.py +0 -199
  197. flexlock-0.8.2/.claude/worktrees/dedup-deps/flexlock/worker_cli.py +0 -138
  198. flexlock-0.8.2/.claude/worktrees/dedup-deps/pixi.lock +0 -5793
  199. flexlock-0.8.2/.claude/worktrees/dedup-deps/pyproject.toml +0 -103
  200. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_api.py +0 -425
  201. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_chained_and_paths.py +0 -227
  202. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_completion_marker.py +0 -154
  203. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_data_hash.py +0 -244
  204. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_debug_enhanced.py +0 -403
  205. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_diff_cli.py +0 -66
  206. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_fingerprint.py +0 -112
  207. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_multistage_config.py +0 -347
  208. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_parallel.py +0 -584
  209. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_resolvers.py +0 -421
  210. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_run_record.py +0 -120
  211. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_save_dir.py +0 -125
  212. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_slurm_validation.py +0 -250
  213. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_submit_params.py +0 -377
  214. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_sweep_semantics.py +0 -312
  215. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_utils.py +0 -923
  216. flexlock-0.8.2/.claude/worktrees/dedup-deps/tests/test_worker_preflight.py +0 -97
  217. flexlock-0.8.2/.gitattributes +0 -2
  218. flexlock-0.8.2/FABLE_IMPLEMENTATION_PLAN.md +0 -368
  219. flexlock-0.8.2/PKG-INFO +0 -357
  220. flexlock-0.8.2/README.md +0 -341
  221. flexlock-0.8.2/bench/taskdb_contention.py +0 -126
  222. flexlock-0.8.2/docs/README.md +0 -23
  223. flexlock-0.8.2/docs/agentic_workflows.md +0 -131
  224. flexlock-0.8.2/docs/api.rst +0 -127
  225. flexlock-0.8.2/docs/cli_reference.md +0 -811
  226. flexlock-0.8.2/docs/conf.py +0 -64
  227. flexlock-0.8.2/docs/dev_plan_task_tags.md +0 -181
  228. flexlock-0.8.2/docs/index.rst +0 -40
  229. flexlock-0.8.2/docs/mlflow_integration.md +0 -960
  230. flexlock-0.8.2/docs/philosophy.md +0 -171
  231. flexlock-0.8.2/docs/python_api.md +0 -905
  232. flexlock-0.8.2/docs/reference.md +0 -305
  233. flexlock-0.8.2/docs/requirements.txt +0 -10
  234. flexlock-0.8.2/docs/upload_docs.sh +0 -17
  235. flexlock-0.8.2/flexlock/api.py +0 -1444
  236. flexlock-0.8.2/flexlock/backends/__init__.py +0 -11
  237. flexlock-0.8.2/flexlock/backends/base.py +0 -41
  238. flexlock-0.8.2/flexlock/context.py +0 -7
  239. flexlock-0.8.2/flexlock/diff.py +0 -253
  240. flexlock-0.8.2/flexlock/diff_cli.py +0 -155
  241. flexlock-0.8.2/flexlock/exceptions.py +0 -50
  242. flexlock-0.8.2/flexlock/export.py +0 -134
  243. flexlock-0.8.2/flexlock/flexcli.py +0 -163
  244. flexlock-0.8.2/flexlock/git_utils.py +0 -196
  245. flexlock-0.8.2/flexlock/mlflow.py +0 -192
  246. flexlock-0.8.2/flexlock/parallel.py +0 -378
  247. flexlock-0.8.2/flexlock/report.py +0 -78
  248. flexlock-0.8.2/flexlock/report_template.html +0 -246
  249. flexlock-0.8.2/flexlock/resolvers.py +0 -248
  250. flexlock-0.8.2/flexlock/run_cli.py +0 -44
  251. flexlock-0.8.2/flexlock/run_record.py +0 -173
  252. flexlock-0.8.2/flexlock/runner.py +0 -571
  253. flexlock-0.8.2/flexlock/skills/flexlock-report/SKILL.md +0 -50
  254. flexlock-0.8.2/flexlock/skills/flexlock-run-and-watch/SKILL.md +0 -60
  255. flexlock-0.8.2/flexlock/snapshot.py +0 -245
  256. flexlock-0.8.2/flexlock/status_cli.py +0 -299
  257. flexlock-0.8.2/flexlock/worker.py +0 -228
  258. flexlock-0.8.2/pixi.lock +0 -5793
  259. flexlock-0.8.2/plan_ergonomics_fable.md +0 -200
  260. flexlock-0.8.2/suggested_improvements.md +0 -126
  261. flexlock-0.8.2/tests/test_chained_and_paths.py +0 -227
  262. flexlock-0.8.2/tests/test_check.py +0 -62
  263. flexlock-0.8.2/tests/test_cli.py +0 -488
  264. flexlock-0.8.2/tests/test_debug_integration.py +0 -105
  265. flexlock-0.8.2/tests/test_deferred.py +0 -98
  266. flexlock-0.8.2/tests/test_diff.py +0 -559
  267. flexlock-0.8.2/tests/test_dump_enqueue.py +0 -274
  268. flexlock-0.8.2/tests/test_fingerprint.py +0 -112
  269. flexlock-0.8.2/tests/test_flexcli.py +0 -89
  270. flexlock-0.8.2/tests/test_flexcli_jupyter.py +0 -201
  271. flexlock-0.8.2/tests/test_git_utils.py +0 -181
  272. flexlock-0.8.2/tests/test_index.py +0 -202
  273. flexlock-0.8.2/tests/test_load_stage.py +0 -176
  274. flexlock-0.8.2/tests/test_mlflowlink.py +0 -246
  275. flexlock-0.8.2/tests/test_node_selection.py +0 -524
  276. flexlock-0.8.2/tests/test_progressive_framework.py +0 -136
  277. flexlock-0.8.2/tests/test_query.py +0 -371
  278. flexlock-0.8.2/tests/test_report.py +0 -104
  279. flexlock-0.8.2/tests/test_runner.py +0 -293
  280. flexlock-0.8.2/tests/test_skills.py +0 -72
  281. flexlock-0.8.2/tests/test_snapshot.py +0 -437
  282. flexlock-0.8.2/tests/test_target_includes.py +0 -135
  283. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/README.md +0 -0
  284. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/conf.py +0 -0
  285. {flexlock-0.8.2 → flexlock-0.10.0}/docs/debugging.md +0 -0
  286. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/mlflow_integration.md +0 -0
  287. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/requirements.txt +0 -0
  288. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/docs/upload_docs.sh +0 -0
  289. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/backends/__init__.py +0 -0
  290. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/backends/base.py +0 -0
  291. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/context.py +0 -0
  292. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/flexcli.py +0 -0
  293. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/report.py +0 -0
  294. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/run_cli.py +0 -0
  295. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/skills/flexlock-report/SKILL.md +0 -0
  296. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/flexlock/status_cli.py +0 -0
  297. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_check.py +0 -0
  298. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_cli.py +0 -0
  299. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_debug_integration.py +0 -0
  300. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_deferred.py +0 -0
  301. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_diff.py +0 -0
  302. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_dump_enqueue.py +0 -0
  303. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_flexcli.py +0 -0
  304. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_flexcli_jupyter.py +0 -0
  305. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_git_utils.py +0 -0
  306. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_load_stage.py +0 -0
  307. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_mlflowlink.py +0 -0
  308. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_node_selection.py +0 -0
  309. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_progressive_framework.py +0 -0
  310. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_query.py +0 -0
  311. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_report.py +0 -0
  312. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_runner.py +0 -0
  313. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_save_dir.py +0 -0
  314. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_skills.py +0 -0
  315. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_snapshot.py +0 -0
  316. {flexlock-0.8.2/.claude/worktrees/dedup-deps → flexlock-0.10.0}/tests/test_target_includes.py +0 -0
  317. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_utils.py +0 -0
  318. {flexlock-0.8.2 → flexlock-0.10.0}/tests/test_worker_preflight.py +0 -0
@@ -0,0 +1,16 @@
1
+ """Refuse personal filesystem paths in public documentation and shipped skills."""
2
+ import re
3
+ from pathlib import Path
4
+ root = Path(__file__).resolve().parents[2]
5
+ paths = [root / "README.md", * (root / "docs").rglob("*.md"),
6
+ *(root / "docs").rglob("*.rst"), *(root / "flexlock/skills").rglob("*.md")]
7
+ bad = []
8
+ for path in paths:
9
+ if "_build" in path.parts:
10
+ continue
11
+ for number, line in enumerate(path.read_text().splitlines(), 1):
12
+ if re.search(r"/(?:ontap|scale|home|jobscratch)/", line):
13
+ bad.append(f"{path.relative_to(root)}:{number}")
14
+ if bad:
15
+ raise SystemExit("Personal filesystem paths in public docs: " + ", ".join(bad))
16
+ print("Public documentation path check passed")
@@ -0,0 +1,35 @@
1
+ """Check that the version declarations agree (and match the tag, if given).
2
+
3
+ The wheel version comes from ``flexlock/__init__.py`` (hatch dynamic version);
4
+ the conda package version from ``[tool.pixi.package] version`` in
5
+ pyproject.toml. Usage: ``python .github/scripts/check_version.py [vX.Y.Z]``.
6
+ """
7
+
8
+ import re
9
+ import sys
10
+ import tomllib
11
+ from pathlib import Path
12
+
13
+ root = Path(__file__).resolve().parents[2]
14
+ init = (root / "flexlock" / "__init__.py").read_text()
15
+ m = re.search(r'^__version__\s*=\s*"([^"]+)"', init, re.M)
16
+ if not m:
17
+ sys.exit("could not find __version__ in flexlock/__init__.py")
18
+ py_version = m.group(1)
19
+
20
+ pixi_version = tomllib.loads((root / "pyproject.toml").read_text())["tool"]["pixi"]["package"]["version"]
21
+
22
+ errors = []
23
+ if py_version != pixi_version:
24
+ errors.append(
25
+ f"flexlock/__init__.py __version__={py_version!r} != "
26
+ f"[tool.pixi.package] version={pixi_version!r}"
27
+ )
28
+ if len(sys.argv) > 1:
29
+ tag = sys.argv[1].removeprefix("refs/tags/")
30
+ if tag != f"v{py_version}":
31
+ errors.append(f"tag {tag!r} does not match package version v{py_version}")
32
+
33
+ if errors:
34
+ sys.exit("\n".join(errors))
35
+ print(f"version OK: {py_version}")
@@ -0,0 +1,66 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ tests:
18
+ name: tests (py${{ matrix.python-version }})
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ python-version: ["3.11", "3.12", "3.13"]
24
+ steps:
25
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26
+ with:
27
+ fetch-depth: 0 # git_utils / snapshot tests inspect history
28
+
29
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+ activate-environment: true
33
+
34
+ - name: Install package and test deps
35
+ # Mirrors [tool.pixi.feature.test]; attrs is needed by test_utils.
36
+ run: uv pip install -e . "pytest>=8.3.2,<9" "pytest-mock>=3.14.0,<4" ipython attrs
37
+
38
+ - name: Git identity (tests create repos and commits)
39
+ run: |
40
+ git config --global user.name "flexlock-ci"
41
+ git config --global user.email "flexlock-ci@users.noreply.github.com"
42
+
43
+ - name: Run tests
44
+ run: pytest -q
45
+
46
+ build:
47
+ name: build sdist/wheel
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
51
+
52
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
53
+ with:
54
+ python-version: "3.11"
55
+
56
+ - name: Check version declarations agree
57
+ run: python .github/scripts/check_version.py
58
+
59
+ - run: uv build
60
+
61
+ - name: Wheel installs into a clean venv and imports
62
+ run: |
63
+ uv venv /tmp/wheelcheck
64
+ uv pip install --python /tmp/wheelcheck/bin/python dist/*.whl
65
+ cd /tmp && /tmp/wheelcheck/bin/python -c "import flexlock; print(flexlock.__version__)"
66
+ /tmp/wheelcheck/bin/flexlock --help > /dev/null
@@ -0,0 +1,58 @@
1
+ name: Docs
2
+
3
+ # Builds the Sphinx docs on every PR; deploys to GitHub Pages
4
+ # (https://quentinf00.github.io/flexlock/) on pushes to main.
5
+ # Requires Settings > Pages > Source = "GitHub Actions".
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ pull_request:
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: pages-${{ github.ref }}
17
+ cancel-in-progress: false
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
24
+
25
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
26
+ with:
27
+ python-version: "3.11"
28
+ activate-environment: true
29
+
30
+ - name: Install docs deps
31
+ # Mirrors [tool.pixi.feature.docs]; conf.py imports flexlock.
32
+ run: uv pip install . sphinx myst-parser sphinx-rtd-theme
33
+
34
+ - name: Check portable documentation
35
+ run: python .github/scripts/check_public_docs.py
36
+
37
+ - name: Build HTML
38
+ run: |
39
+ sphinx-build -b html docs docs/_build/html
40
+ touch docs/_build/html/.nojekyll
41
+
42
+ - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
43
+ with:
44
+ path: docs/_build/html
45
+
46
+ deploy:
47
+ if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
48
+ needs: build
49
+ runs-on: ubuntu-latest
50
+ permissions:
51
+ pages: write
52
+ id-token: write
53
+ environment:
54
+ name: github-pages
55
+ url: ${{ steps.deployment.outputs.page_url }}
56
+ steps:
57
+ - id: deployment
58
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
@@ -0,0 +1,93 @@
1
+ name: Release
2
+
3
+ # Push a tag vX.Y.Z (matching flexlock/__init__.py and [tool.pixi.package]
4
+ # version) to build and publish the PyPI and conda packages.
5
+ on:
6
+ push:
7
+ tags: ["v*"]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ build-dist:
14
+ name: build sdist/wheel
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
18
+
19
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
20
+ with:
21
+ python-version: "3.11"
22
+
23
+ - name: Tag matches package versions
24
+ run: python .github/scripts/check_version.py "${GITHUB_REF_NAME}"
25
+
26
+ - run: uv build
27
+
28
+ - name: Wheel installs into a clean venv and imports
29
+ run: |
30
+ uv venv /tmp/wheelcheck
31
+ uv pip install --python /tmp/wheelcheck/bin/python dist/*.whl
32
+ cd /tmp && /tmp/wheelcheck/bin/python -c "import flexlock; print(flexlock.__version__)"
33
+
34
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+ if-no-files-found: error
39
+
40
+ publish-pypi:
41
+ # Enable this repository variable after configuring the corresponding
42
+ # trusted publisher on PyPI. Local twine publishing works independently.
43
+ if: vars.PYPI_TRUSTED_PUBLISHING == 'true'
44
+ name: publish to PyPI (trusted publishing)
45
+ needs: build-dist
46
+ runs-on: ubuntu-latest
47
+ environment:
48
+ name: pypi
49
+ url: https://pypi.org/p/flexlock
50
+ permissions:
51
+ id-token: write # OIDC token for PyPI trusted publishing; no stored secret
52
+ steps:
53
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
54
+ with:
55
+ name: dist
56
+ path: dist/
57
+
58
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
59
+
60
+ conda:
61
+ name: build + upload conda package (anaconda.org/quentinf00)
62
+ runs-on: ubuntu-latest
63
+ env:
64
+ ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_API_TOKEN }}
65
+ environment:
66
+ name: anaconda
67
+ url: https://anaconda.org/quentinf00/flexlock
68
+ steps:
69
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
70
+
71
+ - name: Tag matches package versions
72
+ run: python3 .github/scripts/check_version.py "${GITHUB_REF_NAME}"
73
+
74
+ - uses: prefix-dev/setup-pixi@d3f436a425481402e6a95a1d1fc10331c708cd9e # v0.10.2
75
+ with:
76
+ pixi-version: v0.73.0
77
+ run-install: false
78
+
79
+ - name: Build conda package ([tool.pixi.package], pixi-build-python)
80
+ run: pixi build --output-dir conda-out
81
+
82
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
83
+ with:
84
+ name: conda-package
85
+ path: conda-out/*.conda
86
+ if-no-files-found: error
87
+
88
+ - name: Upload to anaconda.org
89
+ if: env.ANACONDA_API_TOKEN != ''
90
+ run: |
91
+ pixi exec --spec "anaconda-client>=1.14,<1.16" -- \
92
+ binstar -s api.anaconda.org -t "$ANACONDA_API_TOKEN" \
93
+ upload --user quentinf00 --label main conda-out/*.conda
@@ -14,3 +14,6 @@ doc/_build
14
14
  docs/_build
15
15
  docs/_build
16
16
  outputs
17
+
18
+ # Isolated scheduler acceptance runtime artifacts
19
+ acceptance-runs/
@@ -0,0 +1,78 @@
1
+ # 0.10.0
2
+
3
+ - Retire automatic cross-run cache search, marker-based partial-stage resume and
4
+ chained fanout; retain explicit producer selection, named sweeps and ordered stages.
5
+ - Record invocation source scopes separately from shared source capture.
6
+ - Preserve authoritative result records, pre-submission ownership guards, scheduler
7
+ dependencies and matching-worker queue continuation.
8
+ - Publish portable workflow recipes and align shipped agent skills with explicit
9
+ producer selection and fresh-attempt recovery.
10
+
11
+ # Changelog
12
+
13
+ ## 0.10.0rc1 (local candidate, 2026-10-16)
14
+
15
+ - Remove automatic cross-run cache search, submission cache keywords and CLI
16
+ `--check-exists`, `Project.exists/get_result`, and chained fanout APIs.
17
+ - Reject old marker-based stage-resume payloads and worker-time unpinned run
18
+ selectors under scheduler dependencies. Keep explicit future producer bindings.
19
+ - Preserve exact-path reuse, authoritative output validation, recorded queue
20
+ continuation, ordered stages and provenance comparison. Tighten queue ownership
21
+ checks so foreign queues and changed payloads cannot bypass destination guards.
22
+ - Include the unreleased source-attribution and project-feedback fixes described
23
+ in [candidate migration notes](release_0_10.md).
24
+
25
+ This is an isolated validation candidate; no project environment upgrade or
26
+ scientific rerun is implied.
27
+
28
+ ## 0.9.0 (2026-10-02)
29
+
30
+ ### Added
31
+ - Composite pipelines across sweeps, local/HPC workers, and enqueue/dequeue.
32
+ - Full per-stage run records in directories or the task DB, including upstream
33
+ references, code provenance, and code-drift detection.
34
+ - Environment lockfiles in run fingerprints.
35
+ - Preset tracking and `flexlock runs` / `flexlock presets`.
36
+ - `${run:...}` references to completed preset runs and `key=@name` config swaps.
37
+
38
+ ### Fixed
39
+ - Composite task snapshots retain every executed stage instead of overwriting
40
+ earlier stage records. Exports include each stage's inherited code and environment.
41
+
42
+ ### Release infrastructure
43
+ - CI on Python 3.11–3.13, wheel/sdist checks, tag-driven PyPI and conda publishing,
44
+ and GitHub Pages documentation.
45
+
46
+ The unreleased 0.8.3 fixes below are included in this release.
47
+
48
+ ## 0.8.3 (unreleased)
49
+
50
+ ### Fixed
51
+ - **Single HPC / `isolated=True` runs now get a full `run.lock`.** They used to
52
+ keep the submit-time placeholder (`config` = `save_dir` + `_snapshot_` only)
53
+ because the worker stored the real snapshot only in `run.lock.tasks.db`. That
54
+ broke `${run_lock:...}` (`KeyError`), made `flexlock-run -c run.lock` a
55
+ silent no-op, showed empty configs in `show`/`diff`/`ls`, linked no commits
56
+ on `tag`, and let `gc` delete the upstreams of a tagged run. The worker now
57
+ writes the full snapshot (config, fingerprint, git state, `note`) atomically
58
+ when its task owns the master dir. Sweep roots keep their placeholder.
59
+ - Readers (`${run_lock:...}`, `show`/`graph`/`why`/`report`, `flexlock-diff`,
60
+ `ls`/`gc`/`tag`, `load_stage`, lineage, `flexlock-run -c run.lock`) fall back
61
+ to the task-DB snapshot for placeholder `run.lock`s written by older versions.
62
+ - The worker refreshes `run.lock.tasks` when its queue drains, so it is no
63
+ longer left at `[]` after a `wait=False` submit.
64
+ - `force=True` on a single HPC / isolated submission deleted `run.complete` but
65
+ ran nothing: the old `done` row in the task DB was kept by `INSERT OR IGNORE`.
66
+ The task DB is now reset and the task re-executes. The reset also drops the
67
+ cached sqlite connection, which kept writing to the deleted DB file.
68
+ - Slurm backend: forkserver compatibility fix.
69
+ - `docs/hpc_integration.md`: the task DB lives inside `save_dir`, not in its
70
+ parent. The overview section, clobbered by an earlier edit, is restored.
71
+
72
+ ### Added
73
+ - `flexlock.run_record.load_lock_data(run_dir)`: side-effect-free effective
74
+ `run.lock` (placeholder → task-DB snapshot).
75
+ - `flexlock.run_record.materialize_lock(run_dir)`: one-off rewrite of a
76
+ placeholder `run.lock` (keeps `run.lock.placeholder.bak`).
77
+ - `flexlock repair-locks <root> [-n]`: runs `materialize_lock` over a results tree.
78
+ - `flexlock.taskdb.reset_db(db_path)`.
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.5
2
+ Name: flexlock
3
+ Version: 0.10.0
4
+ Summary: A lightweight and painless SciOps library
5
+ Author-email: Quentin Febvre <quentin.febvre@gmail.com>
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: cloudpickle<4,>=3.0.0
9
+ Requires-Dist: gitpython<4,>=3.1.46
10
+ Requires-Dist: joblib<2,>=1.5.2
11
+ Requires-Dist: loguru<0.8,>=0.7.3
12
+ Requires-Dist: omegaconf<3,>=2.3.0
13
+ Requires-Dist: xxhash<4,>=3.5.0
14
+ Description-Content-Type: text/markdown
15
+
16
+ # FlexLock
17
+
18
+ Python configuration and run provenance for research and offline data processing.
19
+
20
+ [Documentation](https://quentinf00.github.io/flexlock/) · MIT licensed
21
+
22
+ FlexLock lets you write a config in Python, select and override it from the CLI,
23
+ and execute locally or through cluster workers. Run records capture configuration,
24
+ declared source/data dependencies, upstream producers, outputs and return values.
25
+
26
+ The **0.10.0 release** removes automatic cross-run cache search and partial-stage
27
+ resume policy. See [breaking changes](docs/release_0_10.md).
28
+
29
+ ## Configuration and execution
30
+
31
+ ```python
32
+ # cfgmod.py
33
+ from flexlock import py2cfg
34
+ from myproject.stages import prepare, train
35
+
36
+ cfg = dict(
37
+ runs_root='/shared/project/runs',
38
+ track='intensity', arm='baseline', run='20261016-seed3',
39
+ run_dir='${runs_root}/${track}/${arm}/${run}',
40
+ upstream_run='/shared/project/runs/preparation/base/20261001/prepare',
41
+ main=py2cfg(train,
42
+ save_dir='${run_dir}/train',
43
+ input_path='${run_lock:${upstream_run},config.output_path}',
44
+ checkpoint_path='${run_dir}/train/model.pt',
45
+ _snapshot_=dict(data=dict(dataset='${...input_path}')),
46
+ _outputs_=dict(model=dict(path='model.pt', sha256=True))),
47
+ )
48
+ ```
49
+
50
+ ```bash
51
+ flexlock-run -d cfgmod.cfg -s main -o upstream_run=/shared/runs/other/prepare
52
+ flexlock-run -d cfgmod.cfg -s main --sweep-file configs/smoke.yaml --n_jobs 2
53
+ flexlock-run -d cfgmod.cfg -s main --slurm-config configs/slurm_gpu.yaml
54
+ ```
55
+
56
+ Choose fresh destinations for independent runs. Occupied run directories raise
57
+ before scheduler submission; active ownership also prevents forced overwrites.
58
+ Use the [workflow recipes](docs/workflow_guidelines.md) for named sweeps, per-item
59
+ destinations and explicit producer selection.
60
+
61
+ Python submission uses the same execution kernel:
62
+
63
+ ```python
64
+ from flexlock import Project
65
+
66
+ project = Project('cfgmod.cfg')
67
+ result = project.submit('main')
68
+ result.raise_on_failure()
69
+ print(result.save_dir, result.result)
70
+ ```
71
+
72
+ ## Provenance and explicit reuse
73
+
74
+ Source snapshots describe the declared repository scope, including include/exclude
75
+ patterns. Data hashes and upstream bindings record what the callable consumed.
76
+ Comparison tools provide evidence for deciding whether preparation remains acceptable
77
+ after a code change; FlexLock does not choose that scientific policy.
78
+
79
+ ```bash
80
+ flexlock-diff /shared/runs/producer_a /shared/runs/producer_b
81
+ ```
82
+
83
+ Consumers bind concrete producer paths with `run_lock`. FlexLock resolves and records
84
+ the selected producer accurately and rejects identity changes at consumption time.
85
+ It does not silently substitute a newer producer.
86
+
87
+ ```python
88
+ selected = project.submit(cfg, save_dir_policy='skip')
89
+ ```
90
+
91
+ `skip` reuses exactly the selected complete destination after authoritative-record
92
+ and declared-output validation. It returns the producer's recorded config. It does
93
+ not certify equivalence to a new config or current source. `force=True` intentionally
94
+ reruns in place and records the new attempt while keeping products in place.
95
+
96
+ ## Sweeps and ordered stages
97
+
98
+ Sweep files keep large cohorts out of comma-separated CLI arguments. Workers claim
99
+ tasks from a shared SQLite queue, allowing many items with a bounded worker allocation.
100
+ Project coverage checks distinguish successful processing, valid empty outcomes,
101
+ exclusions, missing products and failures.
102
+
103
+ CLI `-s prepare train assess` executes selected stages in order on one allocation,
104
+ with distinct provenance and fail-fast execution. Independent pipeline items can run
105
+ in parallel. Stages needing different resources use separate scheduler jobs and
106
+ `--after`, with concrete future producer paths and an accepted-ID ledger.
107
+
108
+ An unchanged recorded queue can continue pending work without rerunning done rows.
109
+ For a partially completed pipeline, explicitly select remaining stages, bind retained
110
+ producers and use fresh destinations. There is no automatic marker-based stage skip.
111
+
112
+ ## Further reading
113
+
114
+ - [Workflow guidelines and five executable recipes](docs/workflow_guidelines.md)
115
+ - [Python API](docs/python_api.md) and [CLI reference](docs/cli_reference.md)
116
+ - [Source attribution](docs/source_attribution.md) and [HPC integration](docs/hpc_integration.md)
117
+ - [Slim-core design](docs/philosophy.md) and [migration notes](docs/release_0_10.md)
118
+
119
+ Install this release with `pip install flexlock==0.10.0` or from the
120
+ `quentinf00` Conda channel. See the migration notes before upgrading existing callers.
@@ -0,0 +1,105 @@
1
+ # FlexLock
2
+
3
+ Python configuration and run provenance for research and offline data processing.
4
+
5
+ [Documentation](https://quentinf00.github.io/flexlock/) · MIT licensed
6
+
7
+ FlexLock lets you write a config in Python, select and override it from the CLI,
8
+ and execute locally or through cluster workers. Run records capture configuration,
9
+ declared source/data dependencies, upstream producers, outputs and return values.
10
+
11
+ The **0.10.0 release** removes automatic cross-run cache search and partial-stage
12
+ resume policy. See [breaking changes](docs/release_0_10.md).
13
+
14
+ ## Configuration and execution
15
+
16
+ ```python
17
+ # cfgmod.py
18
+ from flexlock import py2cfg
19
+ from myproject.stages import prepare, train
20
+
21
+ cfg = dict(
22
+ runs_root='/shared/project/runs',
23
+ track='intensity', arm='baseline', run='20261016-seed3',
24
+ run_dir='${runs_root}/${track}/${arm}/${run}',
25
+ upstream_run='/shared/project/runs/preparation/base/20261001/prepare',
26
+ main=py2cfg(train,
27
+ save_dir='${run_dir}/train',
28
+ input_path='${run_lock:${upstream_run},config.output_path}',
29
+ checkpoint_path='${run_dir}/train/model.pt',
30
+ _snapshot_=dict(data=dict(dataset='${...input_path}')),
31
+ _outputs_=dict(model=dict(path='model.pt', sha256=True))),
32
+ )
33
+ ```
34
+
35
+ ```bash
36
+ flexlock-run -d cfgmod.cfg -s main -o upstream_run=/shared/runs/other/prepare
37
+ flexlock-run -d cfgmod.cfg -s main --sweep-file configs/smoke.yaml --n_jobs 2
38
+ flexlock-run -d cfgmod.cfg -s main --slurm-config configs/slurm_gpu.yaml
39
+ ```
40
+
41
+ Choose fresh destinations for independent runs. Occupied run directories raise
42
+ before scheduler submission; active ownership also prevents forced overwrites.
43
+ Use the [workflow recipes](docs/workflow_guidelines.md) for named sweeps, per-item
44
+ destinations and explicit producer selection.
45
+
46
+ Python submission uses the same execution kernel:
47
+
48
+ ```python
49
+ from flexlock import Project
50
+
51
+ project = Project('cfgmod.cfg')
52
+ result = project.submit('main')
53
+ result.raise_on_failure()
54
+ print(result.save_dir, result.result)
55
+ ```
56
+
57
+ ## Provenance and explicit reuse
58
+
59
+ Source snapshots describe the declared repository scope, including include/exclude
60
+ patterns. Data hashes and upstream bindings record what the callable consumed.
61
+ Comparison tools provide evidence for deciding whether preparation remains acceptable
62
+ after a code change; FlexLock does not choose that scientific policy.
63
+
64
+ ```bash
65
+ flexlock-diff /shared/runs/producer_a /shared/runs/producer_b
66
+ ```
67
+
68
+ Consumers bind concrete producer paths with `run_lock`. FlexLock resolves and records
69
+ the selected producer accurately and rejects identity changes at consumption time.
70
+ It does not silently substitute a newer producer.
71
+
72
+ ```python
73
+ selected = project.submit(cfg, save_dir_policy='skip')
74
+ ```
75
+
76
+ `skip` reuses exactly the selected complete destination after authoritative-record
77
+ and declared-output validation. It returns the producer's recorded config. It does
78
+ not certify equivalence to a new config or current source. `force=True` intentionally
79
+ reruns in place and records the new attempt while keeping products in place.
80
+
81
+ ## Sweeps and ordered stages
82
+
83
+ Sweep files keep large cohorts out of comma-separated CLI arguments. Workers claim
84
+ tasks from a shared SQLite queue, allowing many items with a bounded worker allocation.
85
+ Project coverage checks distinguish successful processing, valid empty outcomes,
86
+ exclusions, missing products and failures.
87
+
88
+ CLI `-s prepare train assess` executes selected stages in order on one allocation,
89
+ with distinct provenance and fail-fast execution. Independent pipeline items can run
90
+ in parallel. Stages needing different resources use separate scheduler jobs and
91
+ `--after`, with concrete future producer paths and an accepted-ID ledger.
92
+
93
+ An unchanged recorded queue can continue pending work without rerunning done rows.
94
+ For a partially completed pipeline, explicitly select remaining stages, bind retained
95
+ producers and use fresh destinations. There is no automatic marker-based stage skip.
96
+
97
+ ## Further reading
98
+
99
+ - [Workflow guidelines and five executable recipes](docs/workflow_guidelines.md)
100
+ - [Python API](docs/python_api.md) and [CLI reference](docs/cli_reference.md)
101
+ - [Source attribution](docs/source_attribution.md) and [HPC integration](docs/hpc_integration.md)
102
+ - [Slim-core design](docs/philosophy.md) and [migration notes](docs/release_0_10.md)
103
+
104
+ Install this release with `pip install flexlock==0.10.0` or from the
105
+ `quentinf00` Conda channel. See the migration notes before upgrading existing callers.
@@ -1,7 +1,7 @@
1
1
  # Agentic Workflows
2
2
 
3
3
  FlexLock already persists everything needed to reconstruct experiment history
4
- (`run.lock`, shadow git commits, data hashes, lineage, the fingerprint index, the
4
+ (`run.lock`, shadow git commits, data hashes, lineage, the
5
5
  task DB, and tags as git refs). This page documents the **machine-readable query
6
6
  commands** that turn that on-disk state into a stable, agent-facing contract, the
7
7
  **shipped skills** that encode common workflows, and the **static HTML report**.
@@ -25,7 +25,7 @@ Every JSON payload is gated by a `schema_version` (currently `1`).
25
25
 
26
26
  ### `flexlock show --format json`
27
27
 
28
- ```json
28
+ ```text
29
29
  {"schema_version":1, "path":"/abs", "kind":"run|sweep_master|sweep_task",
30
30
  "status":"complete|failed|interrupted|running|pending|unknown", "status_detail":null,
31
31
  "timestamp":"...", "note":null, "target":"myproject.train.train",
@@ -46,7 +46,7 @@ DB row; otherwise `run.complete` → `complete`, `run.error` → `failed`, `run.
46
46
 
47
47
  ### `flexlock graph --format json`
48
48
 
49
- ```json
49
+ ```text
50
50
  {"schema_version":1, "root":"/abs", "generated_at":"...",
51
51
  "nodes":[{"id":"/abs/dir","label":"train","kind":"run","status":"complete",
52
52
  "timestamp":"...","note":null,"target":null,"fingerprint":null,"tag":null,
@@ -57,13 +57,13 @@ DB row; otherwise `run.complete` → `complete`, `run.error` → `failed`, `run.
57
57
  ```
58
58
 
59
59
  `id` is a resolved absolute path. `metrics` are the top-level numeric keys of
60
- `results.json`. Edges pointing outside the scanned tree materialise `kind:
60
+ the authoritative return payload (including legacy `results.json`). Edges pointing outside the scanned tree materialise `kind:
61
61
  external` stub nodes so the graph is closed. `--groups` adds size-≥2 clusters of
62
62
  nodes sharing identical tree hashes / data dicts.
63
63
 
64
64
  ### `flexlock why --format json`
65
65
 
66
- ```json
66
+ ```text
67
67
  {"schema_version":1,"run_a":"/a","run_b":"/b","match":false,
68
68
  "diffs":{"config":[...],"git":[...],"data":[...]},
69
69
  "commits":{"main":{"trees_identical":false,
@@ -89,16 +89,16 @@ query command. See [Reference › On-Disk Run Files](reference.md#on-disk-run-fi
89
89
  ## Failure records — `run.error`
90
90
 
91
91
  When a run's user function raises, FlexLock writes a `run.error` JSON sidecar next
92
- to `run.lock` (schema in the [Reference](reference.md#run-error-json-schema-v1)).
92
+ to `run.lock` (schema in the [Reference](reference.md)).
93
93
  Triage a failure without touching sqlite:
94
94
 
95
95
  ```bash
96
96
  flexlock show <run_dir> --format json # .error.exc_type / .error.traceback
97
97
  ```
98
98
 
99
- Classify by `exc_type`: user-code errors (fix + re-run with `--force`) vs.
100
- node/infra faults (CUDA `cudaErrorSystemNotReady`, OOM — retry elsewhere). A
101
- successful re-run clears the stale `run.error`.
99
+ Inspect error and worker ownership before retrying. Code/config/data changes get
100
+ a fresh attempt with explicit retained inputs. In-place force deliberately replaces
101
+ prior provenance; it is not the default recovery.
102
102
 
103
103
  ## Shipped skills
104
104
 
@@ -111,6 +111,11 @@ FlexLock API Reference
111
111
  :undoc-members:
112
112
  :show-inheritance:
113
113
 
114
+ .. automodule:: flexlock.run_record
115
+ :members:
116
+ :undoc-members:
117
+ :show-inheritance:
118
+
114
119
  .. automodule:: flexlock.taskdb
115
120
  :members:
116
121
  :undoc-members:
@@ -0,0 +1,2 @@
1
+ ```{include} ../CHANGELOG.md
2
+ ```