scriptplan 0.9.2__tar.gz → 0.10.2__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 (294) hide show
  1. scriptplan-0.10.2/CHANGELOG.md +348 -0
  2. {scriptplan-0.9.2 → scriptplan-0.10.2}/MANIFEST.in +2 -0
  3. {scriptplan-0.9.2/scriptplan.egg-info → scriptplan-0.10.2}/PKG-INFO +91 -47
  4. scriptplan-0.10.2/README.md +252 -0
  5. scriptplan-0.10.2/examples/README.md +42 -0
  6. scriptplan-0.10.2/examples/edge_cases/alap_before_declared_start.expected.csv +5 -0
  7. scriptplan-0.10.2/examples/edge_cases/alap_before_declared_start.expected.md +6 -0
  8. scriptplan-0.10.2/examples/edge_cases/alap_before_declared_start.tjp +8 -0
  9. scriptplan-0.10.2/examples/edge_cases/alap_bounded_by_declared_starts.expected.csv +5 -0
  10. scriptplan-0.10.2/examples/edge_cases/alap_bounded_by_declared_starts.expected.md +6 -0
  11. scriptplan-0.10.2/examples/edge_cases/alap_bounded_by_declared_starts.tjp +8 -0
  12. scriptplan-0.10.2/examples/edge_cases/alap_gapduration_before_successor.expected.csv +5 -0
  13. scriptplan-0.10.2/examples/edge_cases/alap_gapduration_before_successor.expected.md +6 -0
  14. scriptplan-0.10.2/examples/edge_cases/alap_gapduration_before_successor.tjp +15 -0
  15. scriptplan-0.10.2/examples/edge_cases/alap_keeps_successor_gaps.expected.csv +7 -0
  16. scriptplan-0.10.2/examples/edge_cases/alap_keeps_successor_gaps.expected.md +8 -0
  17. scriptplan-0.10.2/examples/edge_cases/alap_keeps_successor_gaps.tjp +10 -0
  18. scriptplan-0.10.2/examples/edge_cases/alap_milestones_exact.expected.csv +6 -0
  19. scriptplan-0.10.2/examples/edge_cases/alap_milestones_exact.expected.md +5 -0
  20. scriptplan-0.10.2/examples/edge_cases/alap_milestones_exact.tjp +9 -0
  21. scriptplan-0.10.2/examples/edge_cases/alap_onstart_reading.expected.csv +5 -0
  22. scriptplan-0.10.2/examples/edge_cases/alap_onstart_reading.expected.md +5 -0
  23. scriptplan-0.10.2/examples/edge_cases/alap_onstart_reading.tjp +15 -0
  24. scriptplan-0.10.2/examples/edge_cases/alap_own_end_before_successor.expected.csv +5 -0
  25. scriptplan-0.10.2/examples/edge_cases/alap_own_end_before_successor.expected.md +5 -0
  26. scriptplan-0.10.2/examples/edge_cases/alap_own_end_before_successor.tjp +15 -0
  27. scriptplan-0.10.2/examples/edge_cases/alap_project_end_and_declared_end.expected.csv +4 -0
  28. scriptplan-0.10.2/examples/edge_cases/alap_project_end_and_declared_end.expected.md +5 -0
  29. scriptplan-0.10.2/examples/edge_cases/alap_project_end_and_declared_end.tjp +7 -0
  30. scriptplan-0.10.2/examples/edge_cases/alap_spans_before_mid_slot_successor.expected.csv +5 -0
  31. scriptplan-0.10.2/examples/edge_cases/alap_spans_before_mid_slot_successor.expected.md +5 -0
  32. scriptplan-0.10.2/examples/edge_cases/alap_spans_before_mid_slot_successor.tjp +8 -0
  33. scriptplan-0.10.2/examples/edge_cases/alap_without_anchor_parent.expected.csv +5 -0
  34. scriptplan-0.10.2/examples/edge_cases/alap_without_anchor_parent.expected.md +6 -0
  35. scriptplan-0.10.2/examples/edge_cases/alap_without_anchor_parent.tjp +15 -0
  36. scriptplan-0.10.2/examples/edge_cases/alap_without_anchor_plan.expected.csv +5 -0
  37. scriptplan-0.10.2/examples/edge_cases/alap_without_anchor_plan.expected.md +6 -0
  38. scriptplan-0.10.2/examples/edge_cases/alap_without_anchor_plan.tjp +15 -0
  39. scriptplan-0.10.2/examples/edge_cases/asap_and_alap_share_a_slot.expected.csv +4 -0
  40. scriptplan-0.10.2/examples/edge_cases/asap_and_alap_share_a_slot.expected.md +5 -0
  41. scriptplan-0.10.2/examples/edge_cases/asap_and_alap_share_a_slot.tjp +7 -0
  42. scriptplan-0.10.2/examples/edge_cases/daily_cap_counts_worked_time.expected.csv +4 -0
  43. scriptplan-0.10.2/examples/edge_cases/daily_cap_counts_worked_time.expected.md +6 -0
  44. scriptplan-0.10.2/examples/edge_cases/daily_cap_counts_worked_time.tjp +7 -0
  45. scriptplan-0.10.2/examples/edge_cases/dependency_offset_one_slot.expected.csv +4 -0
  46. scriptplan-0.10.2/examples/edge_cases/dependency_offset_one_slot.expected.md +5 -0
  47. scriptplan-0.10.2/examples/edge_cases/dependency_offset_one_slot.tjp +8 -0
  48. scriptplan-0.10.2/examples/edge_cases/duration_length_after_mid_slot_end.expected.csv +4 -0
  49. scriptplan-0.10.2/examples/edge_cases/duration_length_after_mid_slot_end.expected.md +5 -0
  50. scriptplan-0.10.2/examples/edge_cases/duration_length_after_mid_slot_end.tjp +7 -0
  51. scriptplan-0.10.2/examples/edge_cases/eight_efforts_fill_whole_days.expected.csv +9 -0
  52. scriptplan-0.10.2/examples/edge_cases/eight_efforts_fill_whole_days.expected.md +5 -0
  53. scriptplan-0.10.2/examples/edge_cases/eight_efforts_fill_whole_days.tjp +12 -0
  54. scriptplan-0.10.2/examples/edge_cases/gaplength_on_project_calendar.expected.csv +5 -0
  55. scriptplan-0.10.2/examples/edge_cases/gaplength_on_project_calendar.expected.md +6 -0
  56. scriptplan-0.10.2/examples/edge_cases/gaplength_on_project_calendar.tjp +15 -0
  57. scriptplan-0.10.2/examples/edge_cases/inherited_start_waits_for_dependency.expected.csv +4 -0
  58. scriptplan-0.10.2/examples/edge_cases/inherited_start_waits_for_dependency.expected.md +6 -0
  59. scriptplan-0.10.2/examples/edge_cases/inherited_start_waits_for_dependency.tjp +19 -0
  60. scriptplan-0.10.2/examples/edge_cases/mid_slot_start_and_end.expected.csv +3 -0
  61. scriptplan-0.10.2/examples/edge_cases/mid_slot_start_and_end.expected.md +4 -0
  62. scriptplan-0.10.2/examples/edge_cases/mid_slot_start_and_end.tjp +7 -0
  63. scriptplan-0.10.2/examples/edge_cases/shared_slot_backward.expected.csv +4 -0
  64. scriptplan-0.10.2/examples/edge_cases/shared_slot_backward.expected.md +4 -0
  65. scriptplan-0.10.2/examples/edge_cases/shared_slot_backward.tjp +7 -0
  66. scriptplan-0.10.2/examples/edge_cases/shared_slot_forward_5min.expected.csv +4 -0
  67. scriptplan-0.10.2/examples/edge_cases/shared_slot_forward_5min.expected.md +6 -0
  68. scriptplan-0.10.2/examples/edge_cases/shared_slot_forward_5min.tjp +7 -0
  69. scriptplan-0.10.2/examples/edge_cases/shared_slot_forward_60min.expected.csv +4 -0
  70. scriptplan-0.10.2/examples/edge_cases/shared_slot_forward_60min.expected.md +6 -0
  71. scriptplan-0.10.2/examples/edge_cases/shared_slot_forward_60min.tjp +7 -0
  72. scriptplan-0.10.2/examples/edge_cases/skipped_time_stays_free.expected.csv +5 -0
  73. scriptplan-0.10.2/examples/edge_cases/skipped_time_stays_free.expected.md +6 -0
  74. scriptplan-0.10.2/examples/edge_cases/skipped_time_stays_free.tjp +8 -0
  75. scriptplan-0.10.2/examples/edge_cases/two_people_finish_together.expected.csv +2 -0
  76. scriptplan-0.10.2/examples/edge_cases/two_people_finish_together.expected.md +5 -0
  77. scriptplan-0.10.2/examples/edge_cases/two_people_finish_together.tjp +6 -0
  78. scriptplan-0.10.2/examples/showcase/airport_retrofit.expected.csv +5 -0
  79. scriptplan-0.10.2/examples/showcase/airport_retrofit.expected.md +84 -0
  80. scriptplan-0.10.2/examples/showcase/airport_retrofit.tjp +80 -0
  81. scriptplan-0.10.2/examples/showcase/airport_stress_test.expected.csv +9 -0
  82. scriptplan-0.10.2/examples/showcase/airport_stress_test.expected.md +106 -0
  83. scriptplan-0.10.2/examples/showcase/airport_stress_test.tjp +110 -0
  84. scriptplan-0.10.2/examples/showcase/airport_ultra_math.expected.csv +6 -0
  85. scriptplan-0.10.2/examples/showcase/airport_ultra_math.expected.md +111 -0
  86. scriptplan-0.10.2/examples/showcase/airport_ultra_math.tjp +160 -0
  87. scriptplan-0.10.2/examples/showcase/airport_ultra_math_report.expected.csv +6 -0
  88. scriptplan-0.10.2/examples/showcase/airport_ultra_math_report.expected.md +30 -0
  89. scriptplan-0.10.2/examples/showcase/airport_ultra_math_report.tjp +152 -0
  90. scriptplan-0.10.2/examples/showcase/alap_backward.expected.csv +4 -0
  91. scriptplan-0.10.2/examples/showcase/alap_backward.expected.md +61 -0
  92. scriptplan-0.10.2/examples/showcase/alap_backward.tjp +44 -0
  93. scriptplan-0.10.2/examples/showcase/atomic.expected.csv +2 -0
  94. scriptplan-0.10.2/examples/showcase/atomic.expected.md +49 -0
  95. scriptplan-0.10.2/examples/showcase/atomic.tjp +31 -0
  96. scriptplan-0.10.2/examples/showcase/blackbox.expected.csv +4 -0
  97. scriptplan-0.10.2/examples/showcase/blackbox.expected.md +86 -0
  98. scriptplan-0.10.2/examples/showcase/blackbox.tjp +51 -0
  99. scriptplan-0.10.2/examples/showcase/bottleneck.expected.csv +5 -0
  100. scriptplan-0.10.2/examples/showcase/bottleneck.expected.md +67 -0
  101. scriptplan-0.10.2/examples/showcase/bottleneck.tjp +55 -0
  102. scriptplan-0.10.2/examples/showcase/eclipse.expected.csv +3 -0
  103. scriptplan-0.10.2/examples/showcase/eclipse.expected.md +60 -0
  104. scriptplan-0.10.2/examples/showcase/eclipse.tjp +43 -0
  105. scriptplan-0.10.2/examples/showcase/failover.expected.csv +2 -0
  106. scriptplan-0.10.2/examples/showcase/failover.expected.md +48 -0
  107. scriptplan-0.10.2/examples/showcase/failover.tjp +37 -0
  108. scriptplan-0.10.2/examples/showcase/jit_supply.expected.csv +7 -0
  109. scriptplan-0.10.2/examples/showcase/jit_supply.expected.md +126 -0
  110. scriptplan-0.10.2/examples/showcase/jit_supply.tjp +58 -0
  111. scriptplan-0.10.2/examples/showcase/math_torture.expected.csv +502 -0
  112. scriptplan-0.10.2/examples/showcase/math_torture.expected.md +208 -0
  113. scriptplan-0.10.2/examples/showcase/math_torture.tjp +3028 -0
  114. scriptplan-0.10.2/examples/showcase/paradox.expected.csv +4 -0
  115. scriptplan-0.10.2/examples/showcase/paradox.expected.md +89 -0
  116. scriptplan-0.10.2/examples/showcase/paradox.tjp +48 -0
  117. scriptplan-0.10.2/examples/showcase/priority_clash.expected.csv +4 -0
  118. scriptplan-0.10.2/examples/showcase/priority_clash.expected.md +36 -0
  119. scriptplan-0.10.2/examples/showcase/priority_clash.tjp +36 -0
  120. scriptplan-0.10.2/examples/showcase/quota.expected.csv +5 -0
  121. scriptplan-0.10.2/examples/showcase/quota.expected.md +63 -0
  122. scriptplan-0.10.2/examples/showcase/quota.tjp +49 -0
  123. scriptplan-0.10.2/examples/showcase/simple.expected.csv +5 -0
  124. scriptplan-0.10.2/examples/showcase/simple.expected.md +52 -0
  125. scriptplan-0.10.2/examples/showcase/simple.tjp +50 -0
  126. scriptplan-0.10.2/examples/showcase/synchrony.expected.csv +5 -0
  127. scriptplan-0.10.2/examples/showcase/synchrony.expected.md +54 -0
  128. scriptplan-0.10.2/examples/showcase/synchrony.tjp +70 -0
  129. scriptplan-0.10.2/examples/showcase/thermal.expected.csv +4 -0
  130. scriptplan-0.10.2/examples/showcase/thermal.expected.md +82 -0
  131. scriptplan-0.10.2/examples/showcase/thermal.tjp +43 -0
  132. scriptplan-0.10.2/examples/showcase/throughput.expected.csv +2 -0
  133. scriptplan-0.10.2/examples/showcase/throughput.expected.md +42 -0
  134. scriptplan-0.10.2/examples/showcase/throughput.tjp +37 -0
  135. scriptplan-0.10.2/examples/showcase/time_traveler.expected.csv +4 -0
  136. scriptplan-0.10.2/examples/showcase/time_traveler.expected.md +75 -0
  137. scriptplan-0.10.2/examples/showcase/time_traveler.tjp +63 -0
  138. scriptplan-0.10.2/examples/showcase/timezone_stress.expected.csv +4 -0
  139. scriptplan-0.10.2/examples/showcase/timezone_stress.expected.md +56 -0
  140. scriptplan-0.10.2/examples/showcase/timezone_stress.tjp +65 -0
  141. scriptplan-0.10.2/examples/showcase/tutorial.expected.csv +16 -0
  142. scriptplan-0.10.2/examples/showcase/tutorial.expected.md +448 -0
  143. scriptplan-0.10.2/examples/showcase/tutorial.tjp +494 -0
  144. scriptplan-0.10.2/examples/showcase/union_contract.expected.csv +6 -0
  145. scriptplan-0.10.2/examples/showcase/union_contract.expected.md +44 -0
  146. scriptplan-0.10.2/examples/showcase/union_contract.tjp +53 -0
  147. scriptplan-0.10.2/examples/showcase/workflow_engine.expected.csv +4 -0
  148. scriptplan-0.10.2/examples/showcase/workflow_engine.expected.md +43 -0
  149. scriptplan-0.10.2/examples/showcase/workflow_engine.tjp +66 -0
  150. scriptplan-0.10.2/examples/simple.tjp +26 -0
  151. {scriptplan-0.9.2 → scriptplan-0.10.2}/pyproject.toml +12 -6
  152. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/__init__.py +5 -7
  153. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/cli/main.py +3 -3
  154. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/cli/plan.py +56 -326
  155. scriptplan-0.10.2/scriptplan/cli/plan_files.py +195 -0
  156. scriptplan-0.10.2/scriptplan/cli/plan_help.py +194 -0
  157. scriptplan-0.10.2/scriptplan/core/allocation_plan.py +171 -0
  158. scriptplan-0.10.2/scriptplan/core/attributes.py +464 -0
  159. scriptplan-0.10.2/scriptplan/core/declared_dates.py +47 -0
  160. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/exceptions.py +319 -319
  161. scriptplan-0.10.2/scriptplan/core/limits.py +335 -0
  162. scriptplan-0.10.2/scriptplan/core/project.py +482 -0
  163. scriptplan-0.10.2/scriptplan/core/project_attributes.py +212 -0
  164. scriptplan-0.10.2/scriptplan/core/project_calendar.py +126 -0
  165. scriptplan-0.10.2/scriptplan/core/project_tree.py +256 -0
  166. scriptplan-0.10.2/scriptplan/core/property.py +100 -0
  167. scriptplan-0.10.2/scriptplan/core/property_list.py +358 -0
  168. scriptplan-0.10.2/scriptplan/core/property_set.py +338 -0
  169. scriptplan-0.10.2/scriptplan/core/property_tree_node.py +334 -0
  170. scriptplan-0.10.2/scriptplan/core/resolution.py +95 -0
  171. scriptplan-0.10.2/scriptplan/core/resource_availability.py +187 -0
  172. scriptplan-0.10.2/scriptplan/core/resource_reporting.py +315 -0
  173. scriptplan-0.10.2/scriptplan/core/resource_scenario.py +357 -0
  174. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/scenario_data.py +1 -2
  175. scriptplan-0.10.2/scriptplan/core/slot_ledger.py +263 -0
  176. scriptplan-0.10.2/scriptplan/core/task_booking.py +289 -0
  177. scriptplan-0.10.2/scriptplan/core/task_dependencies.py +317 -0
  178. scriptplan-0.10.2/scriptplan/core/task_placement.py +465 -0
  179. scriptplan-0.10.2/scriptplan/core/task_resources.py +361 -0
  180. scriptplan-0.10.2/scriptplan/core/task_scenario.py +461 -0
  181. scriptplan-0.10.2/scriptplan/core/task_spans.py +65 -0
  182. scriptplan-0.10.2/scriptplan/core/timezones.py +59 -0
  183. scriptplan-0.10.2/scriptplan/core/units.py +190 -0
  184. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/working_hours.py +78 -70
  185. scriptplan-0.10.2/scriptplan/parser/attribute_apply.py +302 -0
  186. scriptplan-0.10.2/scriptplan/parser/model_pieces.py +215 -0
  187. scriptplan-0.10.2/scriptplan/parser/report_builder.py +223 -0
  188. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/parser/tjp.lark +31 -8
  189. scriptplan-0.10.2/scriptplan/parser/tjp_parser.py +439 -0
  190. scriptplan-0.10.2/scriptplan/parser/transformer_project.py +193 -0
  191. scriptplan-0.10.2/scriptplan/parser/transformer_report.py +285 -0
  192. scriptplan-0.10.2/scriptplan/parser/transformer_resource.py +224 -0
  193. scriptplan-0.10.2/scriptplan/parser/transformer_task.py +339 -0
  194. scriptplan-0.10.2/scriptplan/report/logical_expression.py +393 -0
  195. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/report.py +51 -15
  196. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/report_base.py +27 -6
  197. scriptplan-0.10.2/scriptplan/report/table_cells.py +165 -0
  198. scriptplan-0.10.2/scriptplan/report/table_headers.py +69 -0
  199. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/table_report.py +32 -160
  200. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/task_report.py +4 -7
  201. scriptplan-0.10.2/scriptplan/scheduler/postcheck.py +211 -0
  202. scriptplan-0.10.2/scriptplan/scheduler/preflight.py +152 -0
  203. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/scheduler/scoreboard.py +1 -47
  204. scriptplan-0.10.2/scriptplan/scheduler/stalls.py +89 -0
  205. scriptplan-0.10.2/scriptplan/utils/data_cache.py +9 -0
  206. scriptplan-0.10.2/scriptplan/utils/logger.py +39 -0
  207. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/utils/message_handler.py +129 -241
  208. scriptplan-0.10.2/scriptplan/utils/messages.py +192 -0
  209. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/utils/time.py +1 -1
  210. {scriptplan-0.9.2 → scriptplan-0.10.2/scriptplan.egg-info}/PKG-INFO +91 -47
  211. scriptplan-0.10.2/scriptplan.egg-info/SOURCES.txt +271 -0
  212. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan.egg-info/requires.txt +0 -1
  213. scriptplan-0.10.2/setup.py +17 -0
  214. scriptplan-0.10.2/tests/test_ansi_color.py +24 -0
  215. scriptplan-0.10.2/tests/test_audit_probes.py +78 -0
  216. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_core_resource.py +1 -1
  217. scriptplan-0.10.2/tests/test_dependency_check.py +67 -0
  218. scriptplan-0.10.2/tests/test_examples.py +117 -0
  219. scriptplan-0.10.2/tests/test_failure_messages.py +49 -0
  220. scriptplan-0.10.2/tests/test_fixture_golden.py +63 -0
  221. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_parser.py +2 -2
  222. scriptplan-0.10.2/tests/test_plan_cli.py +139 -0
  223. scriptplan-0.10.2/tests/test_project_isolation.py +89 -0
  224. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_property_set.py +5 -3
  225. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_report.py +2 -2
  226. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_scheduling.py +4 -4
  227. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_scheduling_validation.py +145 -226
  228. scriptplan-0.10.2/tests/test_slot_ledger.py +138 -0
  229. scriptplan-0.10.2/tests/test_stated_dates.py +107 -0
  230. scriptplan-0.10.2/tests/test_threads.py +108 -0
  231. scriptplan-0.9.2/README.md +0 -208
  232. scriptplan-0.9.2/scriptplan/_cython/__init__.py +0 -45
  233. scriptplan-0.9.2/scriptplan/_cython/scoreboard_cy.c +0 -11547
  234. scriptplan-0.9.2/scriptplan/_cython/scoreboard_cy.pyx +0 -174
  235. scriptplan-0.9.2/scriptplan/_cython/time_utils_cy.c +0 -11618
  236. scriptplan-0.9.2/scriptplan/_cython/time_utils_cy.pyx +0 -149
  237. scriptplan-0.9.2/scriptplan/_cython/working_hours_cy.c +0 -11742
  238. scriptplan-0.9.2/scriptplan/_cython/working_hours_cy.pyx +0 -150
  239. scriptplan-0.9.2/scriptplan/core/limits.py +0 -369
  240. scriptplan-0.9.2/scriptplan/core/project.py +0 -948
  241. scriptplan-0.9.2/scriptplan/core/property.py +0 -1323
  242. scriptplan-0.9.2/scriptplan/core/resource_scenario.py +0 -719
  243. scriptplan-0.9.2/scriptplan/core/task_scenario.py +0 -1590
  244. scriptplan-0.9.2/scriptplan/parser/tjp_parser.py +0 -1845
  245. scriptplan-0.9.2/scriptplan/scheduler/batch_processor.py +0 -233
  246. scriptplan-0.9.2/scriptplan/utils/data_cache.py +0 -50
  247. scriptplan-0.9.2/scriptplan/utils/logger.py +0 -246
  248. scriptplan-0.9.2/scriptplan.egg-info/SOURCES.txt +0 -87
  249. scriptplan-0.9.2/setup.py +0 -66
  250. scriptplan-0.9.2/tests/test_batch_processor.py +0 -118
  251. scriptplan-0.9.2/tests/test_logger.py +0 -148
  252. {scriptplan-0.9.2 → scriptplan-0.10.2}/LICENSE +0 -0
  253. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/cli/__init__.py +0 -0
  254. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/__init__.py +0 -0
  255. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/account.py +0 -0
  256. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/allocation.py +0 -0
  257. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/booking.py +0 -0
  258. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/journal.py +0 -0
  259. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/leave.py +0 -0
  260. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/resource.py +0 -0
  261. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/scenario.py +0 -0
  262. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/shift.py +0 -0
  263. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/task.py +0 -0
  264. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/core/timesheet.py +0 -0
  265. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/parser/__init__.py +0 -0
  266. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/parser/macro_processor.py +0 -0
  267. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/py.typed +0 -0
  268. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/__init__.py +0 -0
  269. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/report_context.py +0 -0
  270. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/resource_report.py +0 -0
  271. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/report/text_report.py +0 -0
  272. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/scheduler/__init__.py +0 -0
  273. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan/utils/__init__.py +0 -0
  274. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan.egg-info/dependency_links.txt +0 -0
  275. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan.egg-info/entry_points.txt +0 -0
  276. {scriptplan-0.9.2 → scriptplan-0.10.2}/scriptplan.egg-info/top_level.txt +0 -0
  277. {scriptplan-0.9.2 → scriptplan-0.10.2}/setup.cfg +0 -0
  278. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_account.py +0 -0
  279. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_attribute_base.py +0 -0
  280. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_cli.py +0 -0
  281. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_core_allocation.py +0 -0
  282. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_core_booking.py +0 -0
  283. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_core_project.py +0 -0
  284. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_core_scenario.py +0 -0
  285. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_core_task.py +0 -0
  286. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_journal.py +0 -0
  287. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_macro_processor.py +0 -0
  288. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_message_handler.py +0 -0
  289. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_property_list.py +0 -0
  290. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_property_tree_node.py +0 -0
  291. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_scoreboard.py +0 -0
  292. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_shift.py +0 -0
  293. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_timesheet.py +0 -0
  294. {scriptplan-0.9.2 → scriptplan-0.10.2}/tests/test_utils_time.py +0 -0
@@ -0,0 +1,348 @@
1
+ # Changelog
2
+
3
+ ## 0.10.2
4
+
5
+ 0.10.1 shipped two regressions. This release fixes them and the gaps 0.10.1 listed as
6
+ not fixed. It also fixes the defects found while checking every example project
7
+ against answers worked out without the engine, and the thirteen that Trace reported.
8
+ Several plans that 0.10.1 scheduled silently and wrongly are now refused with an error
9
+ that names the task and the date it cannot keep.
10
+
11
+ ### Regressions in 0.10.1
12
+
13
+ - An alap `duration` or `length` task before a successor that starts inside a slot
14
+ ended after that successor started. Before a task starting at 16:20, a 1-hour
15
+ duration ran 16:00-17:00. It now runs 15:20-16:20. 0.10.0 put it at 15:00-16:00.
16
+ - Time a task skipped to honour a mid-slot start or end was lost to every other task.
17
+ After an alap task that had to end at 14:30, a task free from 14:00 ran 15:00-16:00
18
+ instead of 14:30-15:30. Before a task declared to start at 09:30, a task free from
19
+ 09:00 was pushed to 10:00 instead of using 09:00-09:30.
20
+
21
+ Each booking now holds its own interval of the slot, so time a task skips stays free
22
+ and a task that finishes early frees only what follows it.
23
+
24
+ ### Fixed: wrong schedules
25
+
26
+ - A `duration` or `length` task after a task ending mid-slot started at the top of
27
+ that slot, before its predecessor finished. It now starts when the predecessor ends
28
+ and lasts its duration or length to the second.
29
+ - A `duration` waited for working time. After a task ending Friday 17:00 a 2-hour
30
+ duration ran Monday 09:00-11:00, and it now runs Friday 17:00-19:00. An alap 2-hour
31
+ duration that had to end on a Sunday spanned 48 hours, and it now spans 2.
32
+ - A task's finish depended on `timingresolution` when several people shared its last
33
+ slot, because only the first of them worked it. In `tutorial.tjp` the project ended
34
+ at 12:48, 12:00 or 11:44 depending on the slot size alone. All of them now work the
35
+ last slot, and the answer is the same at every resolution.
36
+ - An alap milestone sat a slot before the moment it had to be at. Before a task
37
+ starting at 16:00 it was placed at 15:00. It now sits at 16:00, and one with no
38
+ successor sits at the project end.
39
+ - An alap task did not keep the gap its successor asked for. With `gapduration 24h`
40
+ it ended where the successor began, and now it ends 24 hours earlier.
41
+ - An alap task with an `end` of its own ignored its successors and could end after
42
+ one had started. It now ends by the earlier of the two.
43
+ - An alap task whose successor states its start was moved to the project start, as
44
+ though nothing bounded it. It now ends as late as that start allows.
45
+ - A `start` inherited from a container overrode the task's dependencies. It is now an
46
+ earliest start, and the task waits for what it depends on.
47
+
48
+ ### Fixed: silent wrong schedules are now errors
49
+
50
+ Each of these exits non-zero with a message naming the task and both dates:
51
+
52
+ - a task that would start before a task it depends on ends, including when its own
53
+ `start` says so, with or without a gap, and for milestones;
54
+ - a stated `end` that a task scheduled as soon as possible, or its container, cannot
55
+ meet, which 0.10.1 overran by hours;
56
+ - a stated `start` that an alap task cannot keep;
57
+ - a stated start or end outside the project window. A start after the window used to
58
+ crash with "Error parsing project file: list index out of range", and an end after
59
+ it was clamped while the milestone was dated outside the project.
60
+
61
+ An alap task that cannot fit before its deadline now names that deadline. A task
62
+ whose successor failed is reported as blocked by it. 0.10.1 blamed the project window
63
+ for the first, and moved the second to the start of the project, booked after the
64
+ deadline.
65
+
66
+ ### Fixed: other
67
+
68
+ - A reference that could mean two tasks with the same id bound whichever came first.
69
+ It is now an error that lists both.
70
+ - `getAllocatedTime()` and timesheet figures credited a shared slot to the last task
71
+ booked in it. 40, 13 and 40 minutes in one hour read as 0, 0 and 2 hours, and now
72
+ read as 0.67, 0.22 and 0.67.
73
+ - Each `ProjectFileParser()` compiled the grammar again (about 0.7 s). The grammar is
74
+ now compiled once per process.
75
+ - The `plan` CLI scheduled every project twice and reported any exception raised
76
+ while scheduling as a parse error. It now schedules each project once and reports
77
+ a scheduling exception as a scheduling error.
78
+ - Projects scheduled in parallel threads shared one message list, one error count
79
+ and one switch that turns error collection on. When one thread finished scheduling,
80
+ another thread's error could raise `TjRuntimeError` out of `schedule()` instead of
81
+ making it return False, and an error in one project could fail another. Each thread
82
+ now has its own messages, error count and switch.
83
+ - An `effort` task with no resource allocated was reported as running outside the
84
+ project window because it "needs more time or more resource availability". It is now
85
+ reported as having effort but no resource to do it.
86
+ - `plan report` printed every engine error as "Error: Error: …". It now prints one
87
+ "Error:".
88
+
89
+ ### Documentation
90
+
91
+ - README described `onstart` as one reading for both directions. For a task scheduled
92
+ as soon as possible it is start-to-start. For one scheduled as late as possible it
93
+ means the task must finish before the predecessor starts.
94
+ - README now says that `length` and `gaplength` count the project's working time, how
95
+ an alap task's end is bounded, and that unkept stated dates are errors.
96
+ - README listed `maxgaplength` among the checked constraints. The syntax has never
97
+ accepted it, and the claim is removed.
98
+
99
+ ### Schedules that move
100
+
101
+ A plan whose dates all fall on its slot grid, with no alap milestones and no
102
+ `duration` across non-working time, schedules as it did in 0.10.1. Of the 24 example
103
+ projects, 22 schedule identically:
104
+
105
+ - `tutorial.tjp`: `spec` ends 14:20 instead of 15:00 on 24 January because three
106
+ developers finish it together, and every task after it moves with it. The project
107
+ ends on 18 April at 11:44 instead of 12:48.
108
+ - `jit_supply.tjp`: the alap milestone `connection_setup.set_deps` sits at 2025-07-18
109
+ 08:00, when `pack` starts, instead of 2025-07-17 16:00.
110
+
111
+ ### Internal API
112
+
113
+ `ResourceScenario.reserve()` returns a list of `SlotBooking`, one per free stretch it
114
+ books. The slot ledger is `slotIntervals`, and `slotFrontUsed` and `slotBackUsed` from
115
+ 0.10.1 are gone. Failure handling moved to `scriptplan.scheduler.stalls`, and stated
116
+ dates are tracked in `scriptplan.core.declared_dates`. `slotSecondsUsed` is now
117
+ exactly the sum of `slotTaskUsage` for every slot.
118
+
119
+ ### Verification
120
+
121
+ The golden snapshots record what the engine produced last time. They catch a change
122
+ but not an error, and 0.10.1 passed all of them. `examples/` now holds an answer for every
123
+ task in the 24 showcase projects and in 24 edge cases, each derived by hand from
124
+ the file and the documented semantics without running ScriptPlan, and compared with an
125
+ hour-level reference scheduler wherever it accepts the file. `tests/test_examples.py`
126
+ runs each project through the `plan` CLI and compares every task to the second. Every
127
+ project passes on 0.10.2, and 13 of the edge cases fail on 0.10.1.
128
+
129
+ `audit/evaluations/probe_placement.py` generates 300 plans that mix effort, duration,
130
+ length and milestones in both directions. It checks that every dependency, stated date
131
+ and span holds, that no slot is overfull, and that no task leaves free time it could
132
+ have used. All 300 pass on 0.10.2, against 28 on 0.10.1 and 14
133
+ on 0.10.0.
134
+
135
+ `tests/test_threads.py` schedules five projects three times each in parallel threads
136
+ and compares every date and message with the same project scheduled alone. It also
137
+ forces one thread to leave error collection while another is still inside it. Its
138
+ three tests fail on the 0.10.1 message handler.
139
+
140
+ The full gate runs on Python 3.9 and 3.13.
141
+
142
+ ## 0.10.1
143
+
144
+ Tasks that shared a timing slot on one resource could be booked into time that
145
+ does not exist. Three tasks of 40, 13 and 40 minutes on one person at
146
+ `timingresolution 60min` all started at 09:00, and the 09:00 slot held 5580
147
+ seconds of work without any warning. Every release from 0.9.0 to 0.10.0 has
148
+ the defect. Trace's scheduling harness found it.
149
+
150
+ When a task finished part-way through a slot, the engine gave the rest of that
151
+ slot back as if the task had booked all of it, even when an earlier task had
152
+ already used the front of the slot. It also placed every later task at the top
153
+ of the slot. Each booking now records where in the slot it sits. Forward work
154
+ fills a slot from its start and backward (`alap`) work from its end, and a task
155
+ that finishes early hands back only the part of its own booking it did not use.
156
+ The same three tasks now run 09:00-09:40, 09:40-09:53 and 09:53-10:33 at any
157
+ resolution.
158
+
159
+ ### Fixed
160
+
161
+ - A task whose first slot was partly used reported its start at the top of that
162
+ slot. At 5-minute resolution the third task above started at 09:50 while the
163
+ second ran until 09:53. It now starts at 09:53.
164
+ - `alap` tasks sharing a slot overbooked it the same way. They now fill it
165
+ backwards from the end without overlapping.
166
+ - When several resources finished a task in the same slot, only one of them
167
+ handed back its unused time. 80 minutes of effort on two people ended at
168
+ 10:00 and cost two hours. It now ends at 09:40 and costs 80 minutes.
169
+ - Time handed back was not returned to `limits`. Under `dailymax 60min` the
170
+ three tasks above took Monday, Tuesday and Wednesday, and the person worked
171
+ 40 minutes on Monday. They now use exactly 60 minutes on Monday and finish on
172
+ Tuesday at 09:33.
173
+ - A task that could start mid-slot because its predecessor ended there was kept
174
+ out of the first part of every slot until it booked something. When the
175
+ resource was busy in that slot, the task lost the same minutes in the next
176
+ one, and a task free to start at 10:00 started at 10:50.
177
+ - A `start` inside a slot was rounded down. `start 2026-10-19-09:30` at 60-minute
178
+ resolution started at 09:00, half an hour before the date in the file. A
179
+ mid-slot `end` on an `alap` task was also rounded down to the start of its
180
+ slot. Both are now honoured to the minute.
181
+ - A milestone after a task that ended mid-slot sat at the top of that slot,
182
+ before its predecessor had finished. It now sits at the moment the
183
+ predecessor ends.
184
+
185
+ ### Schedules that move
186
+
187
+ A plan in which no work starts or ends inside a slot schedules as it did in
188
+ 0.10.0. Results change where efforts are off the slot grid, where an efficiency
189
+ other than 1 makes work end mid-slot, where several resources share a task, and
190
+ where a date falls inside a slot. Of the 24 example projects, 22 schedule
191
+ identically to 0.10.0:
192
+
193
+ - `airport_stress_test.tjp`: `t_install` starts at 11:40 instead of 11:00,
194
+ which is when the electrician finishes `t_crit`. `t_low` starts at 10:20
195
+ instead of 10:00 for the same reason. Both keep the end times they had.
196
+ - `tutorial.tjp`: `test.alpha` ends at 11:36 instead of 12:00 on 3 April because
197
+ both people on it stop together. `test.beta` and the project finish at 12:48
198
+ instead of 13:00, and the `beta` and `done` milestones follow.
199
+
200
+ ### Not fixed in this release
201
+
202
+ A `duration` or `length` task that depends on a task ending mid-slot still
203
+ starts at the top of that slot, before its predecessor has finished. After a
204
+ task ending at 09:40, `duration 2h` is reported as 09:00-11:00. 0.10.0 does the
205
+ same. `TaskScenario.getAllocatedTime()` still credits a shared slot to the last
206
+ task booked in it, although cost is correct.
207
+
208
+ ### Internal API
209
+
210
+ `ResourceScenario.book()` takes a `forward` argument. `reserve()` and
211
+ `release()` are new and return or take a `SlotBooking` from
212
+ `scriptplan.core.slot_ledger`. `markSlotPartiallyUsed()` and
213
+ `releasePartialSlot()` had no callers and are removed. `slotSecondsUsed` also
214
+ counts the time a task skips to honour a mid-slot start or end. To measure the work
215
+ booked in a slot, sum `slotTaskUsage`.
216
+
217
+ ### Verification
218
+
219
+ The probe named "Two tasks sharing one resource never double-book a slot" used
220
+ efforts of whole hours, which never share a slot, and it checked the total
221
+ booked, which stays correct when work overlaps. Every capacity check in the
222
+ harness read `slotSecondsUsed`, and the defect lowered that counter in the same
223
+ step that overbooked the slot. None of them could fail on this defect.
224
+
225
+ `audit/evaluations/probe_slot_sharing.py` checks each slot against what was
226
+ booked into it, compares the CLI's report with dates worked out by hand, and
227
+ runs 360 seeded random plans, 240 of them with efforts anywhere from 1 to 600
228
+ minutes. Against 0.10.0 all nine of its probes fail, including the 490-minute
229
+ day Trace reported, and 115 of those 240 plans break at least one of its
230
+ checks. Against 0.10.1 all nine pass. The harness now sums `slotTaskUsage`
231
+ wherever it measures booked time.
232
+
233
+ ## 0.10.0
234
+
235
+ A readiness audit of 0.9.2 turned every documented claim into a probe that
236
+ drives ScriptPlan through its own API or CLI. 32 of those probes failed. This
237
+ release is what it took to make them pass, and it changes scheduling results.
238
+
239
+ ### Breaking: `effort` is person-time
240
+
241
+ `effort 16h allocate a, b` used to occupy both resources for sixteen hours and
242
+ credit sixteen hours of work. Two resources booked thirty-two hours, four booked
243
+ sixty-four, and the completion date never moved however many were assigned. The
244
+ engine took the largest contribution in each slot rather than the sum, so the
245
+ labour of every resource but one was booked, billed and discarded.
246
+
247
+ Effort is now the amount of work to be done, and each allocated resource
248
+ contributes its own time towards it, as the .tjp format defines it. The same task
249
+ with two resources finishes in half the time and costs what one resource's worth
250
+ of work costs.
251
+
252
+ **Upgrading.** A task whose allocations were meant to work side by side is
253
+ written with `mandatory` and its effort in person-hours:
254
+
255
+ ```
256
+ # before 0.10.0: four hours of a pair working together
257
+ task deploy "Deploy" { effort 4h allocate dev, qa }
258
+
259
+ # 0.10.0 and after
260
+ task deploy "Deploy" { effort 8h allocate dev { mandatory }, qa { mandatory } }
261
+ ```
262
+
263
+ Tasks with a single allocation are unaffected. Of the 24 example projects, 21
264
+ schedule identically to 0.9.2; the three that differ are those that allocate
265
+ more than one resource to a task.
266
+
267
+ ### Breaking: failures are reported as failures
268
+
269
+ `Project.schedule()` always returned `True`, and the CLI exited 0 with empty
270
+ start and end cells. A circular dependency, an effort task with no allocation,
271
+ or a task that did not fit the project window produced a warning nobody saw.
272
+
273
+ Scheduling now returns the real result and names each failing task and why; the
274
+ CLIs exit non-zero. A dependency cycle is rejected before scheduling, naming the
275
+ cycle. An attribute or reference the parser cannot place is an error rather than
276
+ a silent drop, which is how `duration`, `length`, `complete` and `note` reached
277
+ the model for the first time.
278
+
279
+ ### Breaking: the declared project period is honoured
280
+
281
+ The project end was grown by a heuristic before scheduling. It is now taken as
282
+ written, and a task that does not fit is reported. Projects that relied on the
283
+ extension need their period stated honestly.
284
+
285
+ ### Breaking: unimplemented report formats are rejected
286
+
287
+ `ical`, `tjp`, `niku`, `ctags` and MS Project XML were accepted, wrote no file,
288
+ and left the CLI blaming a scheduling problem that did not exist. They now raise
289
+ at parse time. Use `json` or `csv`.
290
+
291
+ ### Fixed
292
+
293
+ - Durations follow one table: `m` is months and `min` is minutes everywhere;
294
+ `duration` and `gapduration` are calendar time, `effort`, `length` and
295
+ `gaplength` working time derived from `dailyworkinghours` and
296
+ `yearlyworkingdays`. `gapduration 2d` was 16 hours; `gaplength 30min` was no
297
+ gap at all; `limits { dailymax 30min }` was a 4800-hour cap.
298
+ - Limits count seconds in the resource's own calendar and admit part of a slot,
299
+ so `dailymax 6.4h` is exact. A resource in Los Angeles capped at four hours a
300
+ day was working five in one of its own days. `dailymin`, `weeklymin`,
301
+ `monthlymax`, `monthlymin`, `maximum` and `minimum` reach the grammar, as do
302
+ `maxend`, `maxstart`, `minend` and `minstart`, and violations are reported.
303
+ - Dates are read in the project's timezone and scheduled in UTC; reports convert
304
+ back. The default working day was compared against the hour of a UTC slot,
305
+ putting a New York project five hours out.
306
+ - Slot size is derived from the times a project uses, so `start 09:30` and a
307
+ shift of `08:13 - 11:59` are exact without setting `timingresolution`. That
308
+ shift was credited with seven hours a day instead of eight and a half.
309
+ - A working-hours interval crossing midnight applies to the following day.
310
+ `fri 22:00 - 06:00` marked Friday morning instead of Saturday.
311
+ - Chains mixing ASAP and ALAP schedule instead of deadlocking.
312
+ - Scheduling twice gives the same dates and the same bookings. The second run
313
+ kept the dates and discarded every booking.
314
+ - Reports honour their own `sorttasks`, `hidetask`, column options and formats,
315
+ and `plan report` renders the reports a project declares rather than
316
+ substituting a three-column one. Descending sort was a no-op, and any filter
317
+ hid every row.
318
+ - `report_id` is a SHA-256 of the rendered result. It hashed the input file, so
319
+ a correct and a broken schedule of the same input shared an id.
320
+ - `mandatory`, `persistent` and per-resource allocation options work; they
321
+ parsed to nothing.
322
+
323
+ ### Removed
324
+
325
+ - The Cython extensions. Under `cdivision` the compiled path computed
326
+ `(0 - 1) % 7` as `-1`, so a resource with a Sunday night shift lost its Monday
327
+ morning in every published wheel and kept it in every source checkout: the
328
+ same file, two schedules, and no test covering the compiled one. The wheel is
329
+ now pure Python and cannot diverge from its source.
330
+ - `scheduler.batch_processor`, `utils.data_cache.DataCache` and `utils.Log`,
331
+ none of which were reachable.
332
+
333
+ ### Performance
334
+
335
+ 500 chained tasks at minute resolution schedule in 3.3s, from 14.4s. A year at
336
+ minute resolution with ten resources takes about 13s, from 58.7s.
337
+
338
+ ### Verification
339
+
340
+ `audit/evaluations/` holds 74 probes across 12 files, each named after the
341
+ behaviour it would falsify and each driving ScriptPlan through its own
342
+ interface. `scripts/ci.sh` runs lint, types, a file-size cap, 411 tests, a
343
+ showcase currency check and the probes. The probes also pass against the built
344
+ wheel installed in a clean virtualenv, so what is verified is what ships.
345
+
346
+ ## 0.9.2 and earlier
347
+
348
+ See the git history.
@@ -1,5 +1,7 @@
1
1
  include LICENSE
2
2
  include README.md
3
+ include CHANGELOG.md
3
4
  include pyproject.toml
4
5
  recursive-include scriptplan *.lark
5
6
  recursive-include scriptplan py.typed
7
+ recursive-include examples *.tjp *.csv *.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scriptplan
3
- Version: 0.9.2
3
+ Version: 0.10.2
4
4
  Summary: A precise project scheduling engine with minute-level accuracy for resource allocation and dependency management.
5
5
  Author-email: Farshid Ashouri <farsheed.ashouri@gmail.com>
6
6
  Maintainer-email: Farshid Ashouri <farsheed.ashouri@gmail.com>
@@ -9,6 +9,7 @@ Project-URL: Homepage, https://github.com/rodmena-limited/scriptplan
9
9
  Project-URL: Documentation, https://github.com/rodmena-limited/scriptplan#readme
10
10
  Project-URL: Bug Tracker, https://github.com/rodmena-limited/scriptplan/issues
11
11
  Project-URL: Source, https://github.com/rodmena-limited/scriptplan
12
+ Project-URL: Changelog, https://github.com/rodmena-limited/scriptplan/blob/main/CHANGELOG.md
12
13
  Keywords: scheduling,project-management,resource-allocation,gantt,critical-path
13
14
  Classifier: Development Status :: 4 - Beta
14
15
  Classifier: Intended Audience :: Developers
@@ -40,7 +41,6 @@ Requires-Dist: build; extra == "dev"
40
41
  Requires-Dist: twine; extra == "dev"
41
42
  Requires-Dist: ruff>=0.1.0; extra == "dev"
42
43
  Requires-Dist: mypy>=1.0.0; extra == "dev"
43
- Requires-Dist: cython>=3.0.0; extra == "dev"
44
44
  Dynamic: license-file
45
45
 
46
46
  <p align="center">
@@ -49,13 +49,12 @@ Dynamic: license-file
49
49
 
50
50
  # ScriptPlan
51
51
 
52
- ![Logic Certified](https://img.shields.io/badge/Logic-Certified_Airport--Grade-success?style=for-the-badge&logo=github)
53
- ![Tests Passed](https://img.shields.io/badge/Stress_Tests-24%2F24_Passed-success?style=for-the-badge)
54
- ![Temporal Physics](https://img.shields.io/badge/Temporal_Physics-Verified-blue?style=for-the-badge)
55
- ![Scheduling](https://img.shields.io/badge/Scheduling-ALAP_%7C_JIT_%7C_Priority-blueviolet?style=for-the-badge)
56
- ![Constraints](https://img.shields.io/badge/Constraints-Hard_Limits_%7C_Quotas-orange?style=for-the-badge)
52
+ ![Tests](https://img.shields.io/badge/tests-496_passing-success?style=for-the-badge)
53
+ ![Probes](https://img.shields.io/badge/audit_probes-85_passing-success?style=for-the-badge)
54
+ ![Python](https://img.shields.io/badge/python-3.9%2B-blue?style=for-the-badge)
55
+ ![Licence](https://img.shields.io/badge/licence-Apache--2.0-lightgrey?style=for-the-badge)
57
56
 
58
- A precise project scheduling engine with minute-level accuracy for resource allocation and dependency management. The syntax is compatible with TaskJuggler (.tjp files).
57
+ A precise project scheduling engine with minute-level accuracy for resource allocation and dependency management. It reads projects written in the .tjp format.
59
58
 
60
59
  ## Installation
61
60
 
@@ -110,11 +109,11 @@ done
110
109
  **Features**:
111
110
  - Output to stdout (Unix philosophy)
112
111
  - Messages to stderr
113
- - SHA256 report_id (content-based hash)
112
+ - SHA256 `report_id` over the rendered result, so it changes when the schedule does
114
113
  - Lowercase column names
115
114
  - No HTML metadata
116
115
  - No file pollution (uses temp directories)
117
- - Safe for concurrent execution (100+ instances)
116
+ - Separate processes do not collide: temporary files and directories are unique per run
118
117
 
119
118
  ### Python API
120
119
 
@@ -132,39 +131,89 @@ for task in project.tasks:
132
131
  print(f"{task.id}: {start} -> {end}")
133
132
  ```
134
133
 
135
- ## System Certified
134
+ Projects can be parsed and scheduled in parallel threads. Messages and the error
135
+ count belong to the thread that produced them, so read
136
+ `get_message_handler_instance().messages` in the thread that called `schedule()`.
136
137
 
137
- **Certification Level**: Airport-Grade / Mission Critical
138
+ ## What is verified
138
139
 
139
- **Capabilities Verified**:
140
+ Each behaviour below has a probe in `audit/evaluations/` that drives ScriptPlan
141
+ through its own API or CLI and asserts the result. They run as part of the test
142
+ suite, and can be run on their own against an installed release:
140
143
 
141
- - **Temporal Physics**: Floating point precision, Timezones, DST awareness, Date Line crossing.
142
-
143
- - **Resource Constraints**: Daily/Weekly limits, Hierarchical quotas, Shift intersections.
144
-
145
- - **Advanced Scheduling**: ALAP (Backward pass), Priority preemption, Smart Resource Selection (Failover).
146
-
147
- - **Workflow Logic**: Atomicity (Contiguous), Perishability (Max Gap), Zero-Buffer Synchronization.
148
-
149
- ## Features
150
-
151
- - Minute-level scheduling precision
152
- - ASAP and ALAP scheduling modes
153
- - Resource allocation with contention handling
154
- - Working hours and shift definitions
155
- - Dependency chains with gap constraints
156
- - Leap year and timezone handling
157
-
158
- ## Accuracy
159
-
160
- ScriptPlan uses integer arithmetic for all time calculations, avoiding floating-point drift. The scheduler correctly handles:
161
-
162
- - Non-standard shift boundaries (e.g., 08:13 - 11:59, 13:07 - 17:47)
163
- - Prime-number effort durations with prime-number gaps
164
- - Resource contention across multi-day tasks
165
- - Calendar gaps (weekends, holidays) vs working time gaps
144
+ ```bash
145
+ audit/evaluations/run_all.sh
146
+ ```
166
147
 
167
- Example: A chain of 500 tasks, each with 73-minute effort and 29-minute gaps, scheduled across leap year boundaries with non-standard shifts, produces exact minute-aligned results.
148
+ **Time**
149
+
150
+ - Dates are read in the project's timezone and scheduled in UTC; reports convert back.
151
+ - Resource shifts follow their own timezone across daylight-saving changes in both directions.
152
+ - A working-hours interval that crosses midnight applies to the following day.
153
+ - Slot size is derived from the times a project uses, so `start 09:30` is honoured
154
+ exactly and a shift of `08:13 - 11:59, 13:07 - 17:47` yields its true 8h26m a day.
155
+ `timingresolution` overrides this.
156
+
157
+ **Units**
158
+
159
+ - Calendar time (`duration`, `gapduration`) and working time (`effort`, `length`,
160
+ `gaplength`) are distinguished, with working time derived from
161
+ `dailyworkinghours` and `yearlyworkingdays`. `m` means months; `min` means minutes.
162
+
163
+ **Resources**
164
+
165
+ - `effort` is person-time: two resources available in a slot contribute two
166
+ slots of it. `mandatory` requires a resource for the task to progress at all;
167
+ `persistent` keeps the one first chosen; `alternative` falls back.
168
+ - `dailymax`, `weeklymax`, `monthlymax`, `maximum` and their `min` counterparts
169
+ block at the cap **and** release in the next period. Periods are counted in the
170
+ resource's own calendar, and a cap smaller than one slot is honoured exactly.
171
+
172
+ **Scheduling**
173
+
174
+ - ASAP and ALAP, including chains that mix the two.
175
+ - A task scheduled as late as possible ends by the earliest of its own `end`, the
176
+ start of each successor (less any gap that successor asks for) and the project
177
+ end. With none of these but a successor scheduled as soon as possible that
178
+ states no start, it is scheduled as soon as possible instead, with a warning.
179
+ - Contention is resolved by priority, then criticalness, then declaration order.
180
+ - The declared project period is never rewritten. A task that does not fit is
181
+ reported, with its name and the reason. A date stated outside the period is an
182
+ error.
183
+ - Scheduling the same project twice produces the same dates and the same bookings.
184
+ - A stated `start` or `end` that the schedule cannot keep, and a task that would
185
+ start before something it depends on finishes, are errors.
186
+ - `length` and `gaplength` count the project's working time, not a resource's:
187
+ a resource on longer hours does not shorten the gap.
188
+ - `maxgapduration`, `maxstart`, `minstart`, `maxend` and `minend` are checked
189
+ once the schedule is complete, and a violation is an error. (`maxgaplength` is
190
+ not part of the syntax and is refused when parsed.)
191
+
192
+ **Honesty**
193
+
194
+ - A project that cannot be scheduled exits non-zero and says why. A dependency
195
+ cycle is rejected before scheduling, naming the cycle.
196
+ - An attribute or reference the parser cannot place is an error, never a silent
197
+ drop.
198
+ - `report_id` is a SHA-256 of the rendered result, so it differs when the
199
+ schedule differs.
200
+
201
+ ## Known limits
202
+
203
+ - `include`, `supplement`, `leaveallowance` and `statussheet` are not implemented.
204
+ - Output formats are JSON and CSV. `ical`, `tjp`, `niku` and MS Project XML are
205
+ rejected at parse time rather than silently producing nothing.
206
+ - Accounts are parsed but not yet modelled, so `chargeset` and `charge` record an
207
+ amount without posting it anywhere.
208
+ - A task reference is first looked up from the referring task's scope, one level
209
+ up for each `!`. When that finds nothing but exactly one task in the project has
210
+ that id, the reference binds to it, so `depends !!pack` inside `delivery` finds
211
+ `delivery.pack`. When two tasks could be meant, the file is refused and both are
212
+ named.
213
+ - `onstart` on a dependency means start-to-start for a task scheduled as soon as
214
+ possible: it may start once the predecessor starts. For a task scheduled as
215
+ late as possible it means the task must finish before the predecessor starts,
216
+ which is ScriptPlan's own reading.
168
217
 
169
218
  ## Example Project
170
219
 
@@ -237,17 +286,12 @@ Apache-2.0
237
286
 
238
287
  ## Acknowledgments
239
288
 
240
- ScriptPlan references [TaskJuggler](https://taskjuggler.org/) solely for **file format compatibility**. We have not used, modified, or copied any TaskJuggler source code. ScriptPlan is an independent, clean-room implementation.
241
-
242
- - The `.tjp` file format is documented publicly and widely used in the project management community
243
- - All scheduling algorithms, parser, and report generation in ScriptPlan are original implementations
244
- - TaskJuggler is mentioned only to indicate that ScriptPlan can read the same project file format
245
-
246
- If you're looking for the original TaskJuggler with its full feature set including interactive HTML reports and GUI tools, please visit [taskjuggler.org](https://taskjuggler.org/).
289
+ ScriptPlan reads the .tjp project file format. It contains no code from any other
290
+ scheduler: the parser, the scheduling algorithms and the reports are its own.
247
291
 
248
292
  ## Why ScriptPlan?
249
293
 
250
- This scheduler is part of Highway Workflow Engine's worker capacity management system. I decided to open-source it for the community to benefit from its precise scheduling capabilities. Thanks to TaskJuggler's established syntax, users can easily adopt ScriptPlan without learning a new format.
294
+ This scheduler is part of Highway Workflow Engine's worker capacity management system. I decided to open-source it for the community to benefit from its precise scheduling capabilities. Because it reads the established .tjp syntax, users can adopt ScriptPlan without learning a new format.
251
295
 
252
296
  Yours,
253
297
  Farshid.