gitgrip 2.0.0a1__tar.gz → 2.0.0a2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. gitgrip-2.0.0a2/PKG-INFO +116 -0
  2. gitgrip-2.0.0a2/README.md +101 -0
  3. gitgrip-2.0.0a2/gitgrip.egg-info/PKG-INFO +116 -0
  4. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gitgrip.egg-info/SOURCES.txt +6 -0
  5. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/lane_workspace_prototype.py +30 -1
  6. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/pyproject.toml +3 -2
  7. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/app.py +204 -10
  8. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/commit.py +88 -2
  9. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/execops.py +12 -1
  10. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/git_review.py +48 -11
  11. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/gitops.py +121 -12
  12. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/review_run.py +45 -11
  13. gitgrip-2.0.0a2/python_cli/review_runners.py +292 -0
  14. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/spec_apply.py +6 -1
  15. gitgrip-2.0.0a2/tests/test_exec_apostrophe_and_oserror.py +279 -0
  16. gitgrip-2.0.0a2/tests/test_exec_single_string_and_materialize_plan.py +442 -0
  17. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_git_review.py +93 -0
  18. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_lane_lifecycle_safety.py +5 -0
  19. gitgrip-2.0.0a2/tests/test_lane_repo_paths_and_all_skipped.py +234 -0
  20. gitgrip-2.0.0a2/tests/test_readme_verbs_exist.py +151 -0
  21. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_cli.py +41 -0
  22. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_runners.py +168 -1
  23. gitgrip-2.0.0a2/tests/test_single_repo_cwd_refusal.py +158 -0
  24. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_version_static.py +2 -2
  25. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_workspace_init_from_topology.py +2 -1
  26. gitgrip-2.0.0a2/tests/test_workspace_init_local_repos.py +120 -0
  27. gitgrip-2.0.0a1/PKG-INFO +0 -13
  28. gitgrip-2.0.0a1/README.md +0 -258
  29. gitgrip-2.0.0a1/gitgrip.egg-info/PKG-INFO +0 -13
  30. gitgrip-2.0.0a1/python_cli/review_runners.py +0 -133
  31. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gitgrip.egg-info/dependency_links.txt +0 -0
  32. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gitgrip.egg-info/entry_points.txt +0 -0
  33. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gitgrip.egg-info/requires.txt +0 -0
  34. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gitgrip.egg-info/top_level.txt +0 -0
  35. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/__init__.py +0 -0
  36. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/__init__.py +0 -0
  37. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/activate.py +0 -0
  38. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/agent_manifest.py +0 -0
  39. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/cli.py +0 -0
  40. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/cross_repo.py +0 -0
  41. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/drivers.py +0 -0
  42. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/introspection.py +0 -0
  43. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/language_drivers.py +0 -0
  44. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/objects.py +0 -0
  45. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/perf.py +0 -0
  46. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/refs.py +0 -0
  47. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/trust.py +0 -0
  48. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/types.py +0 -0
  49. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/units.py +0 -0
  50. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/overlay/workspace_spec.py +0 -0
  51. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2/schemas/gr2-materialization-plan-v1.schema.json +0 -0
  52. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/gr2_overlay/__init__.py +0 -0
  53. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/__init__.py +0 -0
  54. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/cache_materialization_probe.py +0 -0
  55. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/concurrent_event_stress.py +0 -0
  56. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/concurrent_lease_stress.py +0 -0
  57. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/concurrent_workspace_cap_stress.py +0 -0
  58. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/contribution_protocol.py +0 -0
  59. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/cross_mode_lane_stress.py +0 -0
  60. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/jsonl_store.py +0 -0
  61. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/layout_model_probe.py +0 -0
  62. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/propagation_daemon.py +0 -0
  63. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/propagation_state_machine.py +0 -0
  64. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/python_exec_playground.py +0 -0
  65. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/python_hook_runtime_playground.py +0 -0
  66. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/python_migration_playground.py +0 -0
  67. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/python_review_checkout_playground.py +0 -0
  68. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/python_spec_apply_playground.py +0 -0
  69. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/real_git_lane_materialization.py +0 -0
  70. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/real_git_playground.py +0 -0
  71. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/recall_lane_history.py +0 -0
  72. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/repo_maintenance_prototype.py +0 -0
  73. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/prototypes/repo_transport_probe.py +0 -0
  74. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/__init__.py +0 -0
  75. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/__main__.py +0 -0
  76. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/add.py +0 -0
  77. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/branch.py +0 -0
  78. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/channel_bridge.py +0 -0
  79. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/clone_exec.py +0 -0
  80. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/config.py +0 -0
  81. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/env_exec.py +0 -0
  82. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/events.py +0 -0
  83. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/failures.py +0 -0
  84. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/file_exec.py +0 -0
  85. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/grip.py +0 -0
  86. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/grip_cli.py +0 -0
  87. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/hooks.py +0 -0
  88. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/launch_exec.py +0 -0
  89. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/merge_verification.py +0 -0
  90. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/migration.py +0 -0
  91. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/open_gr_review.py +0 -0
  92. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/platform.py +0 -0
  93. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/pr.py +0 -0
  94. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/project_review.py +0 -0
  95. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/prune.py +0 -0
  96. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/push.py +0 -0
  97. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/review.py +0 -0
  98. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/review_dispatch.py +0 -0
  99. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/review_ephemeral.py +0 -0
  100. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/review_rebind.py +0 -0
  101. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/staging_cleanup.py +0 -0
  102. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/syncops.py +0 -0
  103. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/target.py +0 -0
  104. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/python_cli/workspace_snapshot.py +0 -0
  105. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/setup.cfg +0 -0
  106. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_add.py +0 -0
  107. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_agent_manifest_overlay_source.py +0 -0
  108. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_app_event_outcomes.py +0 -0
  109. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_apply_convergence.py +0 -0
  110. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_branch.py +0 -0
  111. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_channel_bridge.py +0 -0
  112. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_clone_materialization.py +0 -0
  113. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_commit.py +0 -0
  114. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_config_base_path_guard.py +0 -0
  115. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_config_overlay.py +0 -0
  116. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_conftest_git_isolation.py +0 -0
  117. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_contribution_protocol.py +0 -0
  118. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_ensure_lane_checkout_reference_clone.py +0 -0
  119. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_env_materialization.py +0 -0
  120. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_event_log_integrity.py +0 -0
  121. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_event_outcome_policy.py +0 -0
  122. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_events.py +0 -0
  123. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_events_torn_line.py +0 -0
  124. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_execops.py +0 -0
  125. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_failure_event_outcome.py +0 -0
  126. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_foreground_launch_runtime.py +0 -0
  127. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_gr2_packaging.py +0 -0
  128. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_gr2_review_receipt.py +0 -0
  129. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_grip_cli.py +0 -0
  130. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_grip_hardening.py +0 -0
  131. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_grip_object_model.py +0 -0
  132. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_grip_snapshot.py +0 -0
  133. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_hook_events.py +0 -0
  134. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_hook_hardening.py +0 -0
  135. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_jsonl_store.py +0 -0
  136. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_lane_create_fork_base_cli.py +0 -0
  137. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_lane_lease_show_json.py +0 -0
  138. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_lane_toml_serialization.py +0 -0
  139. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_launch_primitive.py +0 -0
  140. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_m2_overlay_hindsight.py +0 -0
  141. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_m2_overlay_mem0.py +0 -0
  142. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_m2_overlay_zep.py +0 -0
  143. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_materialization_plan_contract.py +0 -0
  144. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_merge_evidence.py +0 -0
  145. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_merge_parent_verification.py +0 -0
  146. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_migration.py +0 -0
  147. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_migration_overlay_compatibility.py +0 -0
  148. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_no_bare_python_cli_imports.py +0 -0
  149. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_null_current_lane_refusal.py +0 -0
  150. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_open_gr_enter.py +0 -0
  151. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_open_project_refusal_reason_cli.py +0 -0
  152. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_acceptance.py +0 -0
  153. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_activate.py +0 -0
  154. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_cli.py +0 -0
  155. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_cli_wiring.py +0 -0
  156. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_composition_merge.py +0 -0
  157. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_cross_repo_atomic_apply.py +0 -0
  158. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_cross_repo_perf_gate.py +0 -0
  159. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_cross_repo_rollback.py +0 -0
  160. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_driver_registry.py +0 -0
  161. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_introspection.py +0 -0
  162. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_multi_stack.py +0 -0
  163. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_object_encoding.py +0 -0
  164. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_perf_gates.py +0 -0
  165. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_python_driver.py +0 -0
  166. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_tier_b_encoding.py +0 -0
  167. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_tier_b_perf_gates.py +0 -0
  168. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_tier_b_repo_state.py +0 -0
  169. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_tier_b_staging_discipline.py +0 -0
  170. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_trust_model.py +0 -0
  171. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_overlay_workspace_spec.py +0 -0
  172. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_pr_events.py +0 -0
  173. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_pr_merge_method.py +0 -0
  174. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_pr_merge_partial_failure.py +0 -0
  175. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_project_file_materialization.py +0 -0
  176. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_project_review_range_reconstruction.py +0 -0
  177. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_project_review_three_repo.py +0 -0
  178. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_projection_tracked_dest.py +0 -0
  179. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_propagation_contribution.py +0 -0
  180. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_propagation_daemon.py +0 -0
  181. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_propagation_state_machine.py +0 -0
  182. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_prune.py +0 -0
  183. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_push.py +0 -0
  184. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_repo_status_linked_worktree.py +0 -0
  185. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_repo_status_schema_version.py +0 -0
  186. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_repo_status_symlinked_git_dir.py +0 -0
  187. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_bind_fork_base.py +0 -0
  188. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_bind_from_range.py +0 -0
  189. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_bind_verify.py +0 -0
  190. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_close_gr.py +0 -0
  191. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_create_project_cli.py +0 -0
  192. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_dispatch.py +0 -0
  193. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_ephemeral.py +0 -0
  194. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_open_lane.py +0 -0
  195. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_rebind.py +0 -0
  196. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_run.py +0 -0
  197. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_run_import_isolation.py +0 -0
  198. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_run_rerun_and_refusal_receipt.py +0 -0
  199. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_review_verify_inside.py +0 -0
  200. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_rmtree_or_refuse.py +0 -0
  201. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_snapshot_id_prefix_resolution.py +0 -0
  202. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_spec_apply_event_outcomes.py +0 -0
  203. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_sprint21_sync_platform.py +0 -0
  204. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_staging_cleanup.py +0 -0
  205. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_store_verb_rename.py +0 -0
  206. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_sync_event_outcomes.py +0 -0
  207. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_sync_fast_forward.py +0 -0
  208. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_sync_fetch.py +0 -0
  209. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_sync_seed_local.py +0 -0
  210. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_sync_ssh_rewrite.py +0 -0
  211. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_sync_status_probe.py +0 -0
  212. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_target.py +0 -0
  213. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_tmux_launch_runtime.py +0 -0
  214. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_unit_abort.py +0 -0
  215. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_unit_apply.py +0 -0
  216. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_unit_apply_dry_run.py +0 -0
  217. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_unit_manifest_schema.py +0 -0
  218. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_unit_propose.py +0 -0
  219. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_unit_topological_apply.py +0 -0
  220. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_workspace_convert_clone.py +0 -0
  221. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_workspace_edit_lease_cap.py +0 -0
  222. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_workspace_identity_boundary.py +0 -0
  223. {gitgrip-2.0.0a1 → gitgrip-2.0.0a2}/tests/test_workspace_snapshot.py +0 -0
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitgrip
3
+ Version: 2.0.0a2
4
+ Summary: Workspace layer for multi-repo work: workspaces, isolated lanes, and one grouped review per slice
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: typer>=0.9
8
+ Requires-Dist: tomli_w>=1.0
9
+ Requires-Dist: pyyaml>=6.0
10
+ Requires-Dist: toml>=0.10
11
+ Requires-Dist: jsonschema>=4.18
12
+ Provides-Extra: dev
13
+ Requires-Dist: pytest>=8.0; extra == "dev"
14
+ Requires-Dist: ruff>=0.4; extra == "dev"
15
+
16
+ # gr2
17
+
18
+ **gr2 is the workspace layer for multi-repo work.** One repository is just git; when a change spans repositories — a feature slice, a release, several agents touching several repos — gr2 gives you a workspace over them, isolated lanes to work in, and one grouped review/PR set for the slice. It is the Python successor to the Rust `gr` (1.x, called gr1 below); both ship from this repository, and `gr2` is the command for the workspace and the slice.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ python3 -m venv ~/gr2-venv && source ~/gr2-venv/bin/activate
24
+ pip install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
25
+ gr2 --version
26
+ ```
27
+
28
+ `--pre` is required while 2.x is an alpha — without it pip installs 1.5.1, which is gr1. To run unreleased development code instead, install from a checkout: `pip install -e gr2/` from the repository root.
29
+
30
+ The Rust `gr` (gr1, 1.x) installs with `brew install synapt-dev/tap/gitgrip` or `cargo install gitgrip`. The two do not collide; you can have both installed.
31
+
32
+ ## First five minutes
33
+
34
+ Every command below was run, in this order, in a clean virtualenv against a throwaway workspace of two repositories. Put two clones side by side in one folder, say `~/ws/repo-a` and `~/ws/repo-b`.
35
+
36
+ ```bash
37
+ cd ~/ws
38
+ gr2 workspace init ~/ws # scans the folder; writes .grip/workspace_spec.toml
39
+ gr2 workspace materialize ~/ws --yes # builds the .grip layout and a default unit
40
+ gr2 workspace status ~/ws # what kind of workspace this is
41
+ gr2 store init ~/ws # the workspace snapshot store (needed before review)
42
+ ```
43
+
44
+ A **unit** is one worker — you, or one agent — and `default` is created for you. A **lane** is one piece of work spanning repos, with its own clones, so two lanes never step on each other:
45
+
46
+ ```bash
47
+ gr2 lane create ~/ws default feat-x --repos repo-a,repo-b --branch feat/x
48
+ gr2 lane enter ~/ws default feat-x --actor human:you
49
+ ```
50
+
51
+ Both commands print, per repo, the absolute directory you work in:
52
+
53
+ ```
54
+ repo-a: ~/ws/.grip/state/lanes/default/feat-x/repos/repo-a
55
+ repo-b: ~/ws/.grip/state/lanes/default/feat-x/repos/repo-b
56
+ ```
57
+
58
+ Edit there — not in your original clones. Stage and commit across the lane's repos:
59
+
60
+ ```bash
61
+ gr2 add . --repo-path ~/ws/.grip/state/lanes/default/feat-x/repos/repo-a
62
+ gr2 commit -m "my change" --workspace-root ~/ws --owner-unit default
63
+ ```
64
+
65
+ `commit` with the lane flags commits every lane repo that has staged changes and names the repos it skipped. If every repo was skipped it exits non-zero with one sentence naming where it looked — and, when it can see them, where your staged changes actually are. Run one command across every lane repo, then turn the lane into one reviewable object:
66
+
67
+ ```bash
68
+ gr2 exec run ~/ws default --actor human:you -- pytest -q # one command, every lane repo
69
+ gr2 review create-project ~/ws default feat-x # prints gr:<sha>: one object to review
70
+ gr2 lane current ~/ws default # where am I?
71
+ gr2 lane exit ~/ws default --actor human:you
72
+ ```
73
+
74
+ `exec run` and `lane exit` require `--actor`. Every group and verb takes `--help`; `gr2 --help` lists them all.
75
+
76
+ ## What works today, and what is not there yet
77
+
78
+ Alpha 2 is a working local workspace layer. Verified by running the walk above:
79
+
80
+ - `workspace` (init, materialize, status, migrate-gr1 from a gr1 gripspace), `lane` (create, enter, exit, current, lease), `store` (init, snapshot, log, diff, checkout), `exec run`, `repo status`, `sync status`, `review create-project`.
81
+ - Lanes are independent clones: two lanes, or two agents, never share refs, an index, or a working tree.
82
+ - A lane commit that commits nothing anywhere refuses loudly instead of reporting success.
83
+
84
+ Not there yet:
85
+
86
+ - The full walk with **remote** PRs (`gr2 push`, `gr2 pr create`) is documented in `--help` but was not exercised in a clean environment for this README; treat those two as alpha.
87
+ - `gr2 --help` and some verb output still say "prototype" in places; the wording is being cleaned up as verbs land.
88
+ - The Rust `gr` (gr1) still owns `spawn`, `fleet`, and `manifest` until their gr2 ports land. Everything else — workspace sync, lanes, the multi-repo slice, its review — is gr2's job; if a verb is missing or wrong there, that is a bug worth reporting, not a reason to reach for gr1.
89
+
90
+ ## Commands
91
+
92
+ | Group | Verbs |
93
+ |---|---|
94
+ | `workspace` | init, init-from-topology, materialize, status, convert-clone, detect-gr1, migrate-gr1, migrate-lane-state, bootstrap-gr1 |
95
+ | `spec` | show, validate |
96
+ | `lane` | create, enter, exit, current, resolve, bind, lease |
97
+ | (top level) | branch, add, commit, push, prune |
98
+ | `sync` | status, run |
99
+ | `pr` | create, status, checks, merge |
100
+ | `review` | open, close, checkout-pr, run, requirements, bind, verify, rebind, create-project |
101
+ | `exec` | status, run |
102
+ | `repo` | status, hooks, hook-run, projection-run |
103
+ | `store` | init, snapshot, log, diff, checkout |
104
+ | `target`, `config`, `plan`, `apply` | stored PR target; config overlays; show/apply the materialization plan |
105
+
106
+ ## Overlay substrate
107
+
108
+ gr2 also carries the config-overlay substrate (capture, compose, and materialize configuration layers over a workspace): see [docs/OVERLAY-SUBSTRATE.md](docs/OVERLAY-SUBSTRATE.md).
109
+
110
+ ## Development
111
+
112
+ ```bash
113
+ pip install -e "gr2[dev]" # from the repository root
114
+ cd gr2 && pytest # the gr2 suite (tests + overlay tests)
115
+ cd gr2 && ruff check . # lint, same config as CI
116
+ ```
@@ -0,0 +1,101 @@
1
+ # gr2
2
+
3
+ **gr2 is the workspace layer for multi-repo work.** One repository is just git; when a change spans repositories — a feature slice, a release, several agents touching several repos — gr2 gives you a workspace over them, isolated lanes to work in, and one grouped review/PR set for the slice. It is the Python successor to the Rust `gr` (1.x, called gr1 below); both ship from this repository, and `gr2` is the command for the workspace and the slice.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ python3 -m venv ~/gr2-venv && source ~/gr2-venv/bin/activate
9
+ pip install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
10
+ gr2 --version
11
+ ```
12
+
13
+ `--pre` is required while 2.x is an alpha — without it pip installs 1.5.1, which is gr1. To run unreleased development code instead, install from a checkout: `pip install -e gr2/` from the repository root.
14
+
15
+ The Rust `gr` (gr1, 1.x) installs with `brew install synapt-dev/tap/gitgrip` or `cargo install gitgrip`. The two do not collide; you can have both installed.
16
+
17
+ ## First five minutes
18
+
19
+ Every command below was run, in this order, in a clean virtualenv against a throwaway workspace of two repositories. Put two clones side by side in one folder, say `~/ws/repo-a` and `~/ws/repo-b`.
20
+
21
+ ```bash
22
+ cd ~/ws
23
+ gr2 workspace init ~/ws # scans the folder; writes .grip/workspace_spec.toml
24
+ gr2 workspace materialize ~/ws --yes # builds the .grip layout and a default unit
25
+ gr2 workspace status ~/ws # what kind of workspace this is
26
+ gr2 store init ~/ws # the workspace snapshot store (needed before review)
27
+ ```
28
+
29
+ A **unit** is one worker — you, or one agent — and `default` is created for you. A **lane** is one piece of work spanning repos, with its own clones, so two lanes never step on each other:
30
+
31
+ ```bash
32
+ gr2 lane create ~/ws default feat-x --repos repo-a,repo-b --branch feat/x
33
+ gr2 lane enter ~/ws default feat-x --actor human:you
34
+ ```
35
+
36
+ Both commands print, per repo, the absolute directory you work in:
37
+
38
+ ```
39
+ repo-a: ~/ws/.grip/state/lanes/default/feat-x/repos/repo-a
40
+ repo-b: ~/ws/.grip/state/lanes/default/feat-x/repos/repo-b
41
+ ```
42
+
43
+ Edit there — not in your original clones. Stage and commit across the lane's repos:
44
+
45
+ ```bash
46
+ gr2 add . --repo-path ~/ws/.grip/state/lanes/default/feat-x/repos/repo-a
47
+ gr2 commit -m "my change" --workspace-root ~/ws --owner-unit default
48
+ ```
49
+
50
+ `commit` with the lane flags commits every lane repo that has staged changes and names the repos it skipped. If every repo was skipped it exits non-zero with one sentence naming where it looked — and, when it can see them, where your staged changes actually are. Run one command across every lane repo, then turn the lane into one reviewable object:
51
+
52
+ ```bash
53
+ gr2 exec run ~/ws default --actor human:you -- pytest -q # one command, every lane repo
54
+ gr2 review create-project ~/ws default feat-x # prints gr:<sha>: one object to review
55
+ gr2 lane current ~/ws default # where am I?
56
+ gr2 lane exit ~/ws default --actor human:you
57
+ ```
58
+
59
+ `exec run` and `lane exit` require `--actor`. Every group and verb takes `--help`; `gr2 --help` lists them all.
60
+
61
+ ## What works today, and what is not there yet
62
+
63
+ Alpha 2 is a working local workspace layer. Verified by running the walk above:
64
+
65
+ - `workspace` (init, materialize, status, migrate-gr1 from a gr1 gripspace), `lane` (create, enter, exit, current, lease), `store` (init, snapshot, log, diff, checkout), `exec run`, `repo status`, `sync status`, `review create-project`.
66
+ - Lanes are independent clones: two lanes, or two agents, never share refs, an index, or a working tree.
67
+ - A lane commit that commits nothing anywhere refuses loudly instead of reporting success.
68
+
69
+ Not there yet:
70
+
71
+ - The full walk with **remote** PRs (`gr2 push`, `gr2 pr create`) is documented in `--help` but was not exercised in a clean environment for this README; treat those two as alpha.
72
+ - `gr2 --help` and some verb output still say "prototype" in places; the wording is being cleaned up as verbs land.
73
+ - The Rust `gr` (gr1) still owns `spawn`, `fleet`, and `manifest` until their gr2 ports land. Everything else — workspace sync, lanes, the multi-repo slice, its review — is gr2's job; if a verb is missing or wrong there, that is a bug worth reporting, not a reason to reach for gr1.
74
+
75
+ ## Commands
76
+
77
+ | Group | Verbs |
78
+ |---|---|
79
+ | `workspace` | init, init-from-topology, materialize, status, convert-clone, detect-gr1, migrate-gr1, migrate-lane-state, bootstrap-gr1 |
80
+ | `spec` | show, validate |
81
+ | `lane` | create, enter, exit, current, resolve, bind, lease |
82
+ | (top level) | branch, add, commit, push, prune |
83
+ | `sync` | status, run |
84
+ | `pr` | create, status, checks, merge |
85
+ | `review` | open, close, checkout-pr, run, requirements, bind, verify, rebind, create-project |
86
+ | `exec` | status, run |
87
+ | `repo` | status, hooks, hook-run, projection-run |
88
+ | `store` | init, snapshot, log, diff, checkout |
89
+ | `target`, `config`, `plan`, `apply` | stored PR target; config overlays; show/apply the materialization plan |
90
+
91
+ ## Overlay substrate
92
+
93
+ gr2 also carries the config-overlay substrate (capture, compose, and materialize configuration layers over a workspace): see [docs/OVERLAY-SUBSTRATE.md](docs/OVERLAY-SUBSTRATE.md).
94
+
95
+ ## Development
96
+
97
+ ```bash
98
+ pip install -e "gr2[dev]" # from the repository root
99
+ cd gr2 && pytest # the gr2 suite (tests + overlay tests)
100
+ cd gr2 && ruff check . # lint, same config as CI
101
+ ```
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitgrip
3
+ Version: 2.0.0a2
4
+ Summary: Workspace layer for multi-repo work: workspaces, isolated lanes, and one grouped review per slice
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: typer>=0.9
8
+ Requires-Dist: tomli_w>=1.0
9
+ Requires-Dist: pyyaml>=6.0
10
+ Requires-Dist: toml>=0.10
11
+ Requires-Dist: jsonschema>=4.18
12
+ Provides-Extra: dev
13
+ Requires-Dist: pytest>=8.0; extra == "dev"
14
+ Requires-Dist: ruff>=0.4; extra == "dev"
15
+
16
+ # gr2
17
+
18
+ **gr2 is the workspace layer for multi-repo work.** One repository is just git; when a change spans repositories — a feature slice, a release, several agents touching several repos — gr2 gives you a workspace over them, isolated lanes to work in, and one grouped review/PR set for the slice. It is the Python successor to the Rust `gr` (1.x, called gr1 below); both ship from this repository, and `gr2` is the command for the workspace and the slice.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ python3 -m venv ~/gr2-venv && source ~/gr2-venv/bin/activate
24
+ pip install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
25
+ gr2 --version
26
+ ```
27
+
28
+ `--pre` is required while 2.x is an alpha — without it pip installs 1.5.1, which is gr1. To run unreleased development code instead, install from a checkout: `pip install -e gr2/` from the repository root.
29
+
30
+ The Rust `gr` (gr1, 1.x) installs with `brew install synapt-dev/tap/gitgrip` or `cargo install gitgrip`. The two do not collide; you can have both installed.
31
+
32
+ ## First five minutes
33
+
34
+ Every command below was run, in this order, in a clean virtualenv against a throwaway workspace of two repositories. Put two clones side by side in one folder, say `~/ws/repo-a` and `~/ws/repo-b`.
35
+
36
+ ```bash
37
+ cd ~/ws
38
+ gr2 workspace init ~/ws # scans the folder; writes .grip/workspace_spec.toml
39
+ gr2 workspace materialize ~/ws --yes # builds the .grip layout and a default unit
40
+ gr2 workspace status ~/ws # what kind of workspace this is
41
+ gr2 store init ~/ws # the workspace snapshot store (needed before review)
42
+ ```
43
+
44
+ A **unit** is one worker — you, or one agent — and `default` is created for you. A **lane** is one piece of work spanning repos, with its own clones, so two lanes never step on each other:
45
+
46
+ ```bash
47
+ gr2 lane create ~/ws default feat-x --repos repo-a,repo-b --branch feat/x
48
+ gr2 lane enter ~/ws default feat-x --actor human:you
49
+ ```
50
+
51
+ Both commands print, per repo, the absolute directory you work in:
52
+
53
+ ```
54
+ repo-a: ~/ws/.grip/state/lanes/default/feat-x/repos/repo-a
55
+ repo-b: ~/ws/.grip/state/lanes/default/feat-x/repos/repo-b
56
+ ```
57
+
58
+ Edit there — not in your original clones. Stage and commit across the lane's repos:
59
+
60
+ ```bash
61
+ gr2 add . --repo-path ~/ws/.grip/state/lanes/default/feat-x/repos/repo-a
62
+ gr2 commit -m "my change" --workspace-root ~/ws --owner-unit default
63
+ ```
64
+
65
+ `commit` with the lane flags commits every lane repo that has staged changes and names the repos it skipped. If every repo was skipped it exits non-zero with one sentence naming where it looked — and, when it can see them, where your staged changes actually are. Run one command across every lane repo, then turn the lane into one reviewable object:
66
+
67
+ ```bash
68
+ gr2 exec run ~/ws default --actor human:you -- pytest -q # one command, every lane repo
69
+ gr2 review create-project ~/ws default feat-x # prints gr:<sha>: one object to review
70
+ gr2 lane current ~/ws default # where am I?
71
+ gr2 lane exit ~/ws default --actor human:you
72
+ ```
73
+
74
+ `exec run` and `lane exit` require `--actor`. Every group and verb takes `--help`; `gr2 --help` lists them all.
75
+
76
+ ## What works today, and what is not there yet
77
+
78
+ Alpha 2 is a working local workspace layer. Verified by running the walk above:
79
+
80
+ - `workspace` (init, materialize, status, migrate-gr1 from a gr1 gripspace), `lane` (create, enter, exit, current, lease), `store` (init, snapshot, log, diff, checkout), `exec run`, `repo status`, `sync status`, `review create-project`.
81
+ - Lanes are independent clones: two lanes, or two agents, never share refs, an index, or a working tree.
82
+ - A lane commit that commits nothing anywhere refuses loudly instead of reporting success.
83
+
84
+ Not there yet:
85
+
86
+ - The full walk with **remote** PRs (`gr2 push`, `gr2 pr create`) is documented in `--help` but was not exercised in a clean environment for this README; treat those two as alpha.
87
+ - `gr2 --help` and some verb output still say "prototype" in places; the wording is being cleaned up as verbs land.
88
+ - The Rust `gr` (gr1) still owns `spawn`, `fleet`, and `manifest` until their gr2 ports land. Everything else — workspace sync, lanes, the multi-repo slice, its review — is gr2's job; if a verb is missing or wrong there, that is a bug worth reporting, not a reason to reach for gr1.
89
+
90
+ ## Commands
91
+
92
+ | Group | Verbs |
93
+ |---|---|
94
+ | `workspace` | init, init-from-topology, materialize, status, convert-clone, detect-gr1, migrate-gr1, migrate-lane-state, bootstrap-gr1 |
95
+ | `spec` | show, validate |
96
+ | `lane` | create, enter, exit, current, resolve, bind, lease |
97
+ | (top level) | branch, add, commit, push, prune |
98
+ | `sync` | status, run |
99
+ | `pr` | create, status, checks, merge |
100
+ | `review` | open, close, checkout-pr, run, requirements, bind, verify, rebind, create-project |
101
+ | `exec` | status, run |
102
+ | `repo` | status, hooks, hook-run, projection-run |
103
+ | `store` | init, snapshot, log, diff, checkout |
104
+ | `target`, `config`, `plan`, `apply` | stored PR target; config overlays; show/apply the materialization plan |
105
+
106
+ ## Overlay substrate
107
+
108
+ gr2 also carries the config-overlay substrate (capture, compose, and materialize configuration layers over a workspace): see [docs/OVERLAY-SUBSTRATE.md](docs/OVERLAY-SUBSTRATE.md).
109
+
110
+ ## Development
111
+
112
+ ```bash
113
+ pip install -e "gr2[dev]" # from the repository root
114
+ cd gr2 && pytest # the gr2 suite (tests + overlay tests)
115
+ cd gr2 && ruff check . # lint, same config as CI
116
+ ```
@@ -103,6 +103,8 @@ tests/test_event_log_integrity.py
103
103
  tests/test_event_outcome_policy.py
104
104
  tests/test_events.py
105
105
  tests/test_events_torn_line.py
106
+ tests/test_exec_apostrophe_and_oserror.py
107
+ tests/test_exec_single_string_and_materialize_plan.py
106
108
  tests/test_execops.py
107
109
  tests/test_failure_event_outcome.py
108
110
  tests/test_foreground_launch_runtime.py
@@ -119,6 +121,7 @@ tests/test_jsonl_store.py
119
121
  tests/test_lane_create_fork_base_cli.py
120
122
  tests/test_lane_lease_show_json.py
121
123
  tests/test_lane_lifecycle_safety.py
124
+ tests/test_lane_repo_paths_and_all_skipped.py
122
125
  tests/test_lane_toml_serialization.py
123
126
  tests/test_launch_primitive.py
124
127
  tests/test_m2_overlay_hindsight.py
@@ -165,6 +168,7 @@ tests/test_propagation_daemon.py
165
168
  tests/test_propagation_state_machine.py
166
169
  tests/test_prune.py
167
170
  tests/test_push.py
171
+ tests/test_readme_verbs_exist.py
168
172
  tests/test_repo_status_linked_worktree.py
169
173
  tests/test_repo_status_schema_version.py
170
174
  tests/test_repo_status_symlinked_git_dir.py
@@ -184,6 +188,7 @@ tests/test_review_run_rerun_and_refusal_receipt.py
184
188
  tests/test_review_runners.py
185
189
  tests/test_review_verify_inside.py
186
190
  tests/test_rmtree_or_refuse.py
191
+ tests/test_single_repo_cwd_refusal.py
187
192
  tests/test_snapshot_id_prefix_resolution.py
188
193
  tests/test_spec_apply_event_outcomes.py
189
194
  tests/test_sprint21_sync_platform.py
@@ -208,4 +213,5 @@ tests/test_workspace_convert_clone.py
208
213
  tests/test_workspace_edit_lease_cap.py
209
214
  tests/test_workspace_identity_boundary.py
210
215
  tests/test_workspace_init_from_topology.py
216
+ tests/test_workspace_init_local_repos.py
211
217
  tests/test_workspace_snapshot.py
@@ -195,6 +195,7 @@ class LaneTransitionOutcome:
195
195
  current_lane: str | None
196
196
  state_path: Path
197
197
  status: str = "ok"
198
+ repo_paths: dict[str, str] = dataclasses.field(default_factory=dict)
198
199
 
199
200
  @property
200
201
  def exit_code(self) -> int:
@@ -208,6 +209,7 @@ class LaneTransitionOutcome:
208
209
  "previous_lane": self.previous_lane,
209
210
  "current_lane": self.current_lane,
210
211
  "state_path": str(self.state_path),
212
+ "repo_paths": dict(self.repo_paths),
211
213
  }
212
214
 
213
215
 
@@ -1038,6 +1040,18 @@ def create_lane(args: argparse.Namespace) -> int:
1038
1040
  (lane_root / "context").mkdir()
1039
1041
  atomic_replace_text(metadata_path, expected)
1040
1042
  print(metadata_path)
1043
+ # The human line names where the actor works, per repo, absolute: a
1044
+ # materialized lane's repos live under its lane tree, a bound lane's one
1045
+ # repo IS the bound worktree. (The stranger's F2 finding: enter/create
1046
+ # used to point at lane.toml only, so the actor never learned where the
1047
+ # lane's repos are.)
1048
+ if lane_kind == "bound" and bound_worktree:
1049
+ for repo in repos:
1050
+ print(f"{repo}: {bound_worktree}")
1051
+ else:
1052
+ lane_root = lane_dir(workspace_root, args.owner_unit, args.lane_name)
1053
+ for repo in repos:
1054
+ print(f"{repo}: {lane_root / 'repos' / repo}")
1041
1055
  return 0
1042
1056
 
1043
1057
 
@@ -1222,6 +1236,17 @@ def enter_lane(args: argparse.Namespace) -> LaneTransitionOutcome:
1222
1236
  previous_lane = current.get("lane_name")
1223
1237
  previous.insert(0, current)
1224
1238
 
1239
+ lane_kind = lane_doc.get("lane_kind", "materialized")
1240
+ if lane_kind == "bound" and lane_doc.get("bound_worktree"):
1241
+ repo_paths = {
1242
+ r: str(lane_doc["bound_worktree"]) for r in lane_doc.get("repos", [])
1243
+ }
1244
+ else:
1245
+ lane_root = lane_dir(workspace_root, args.owner_unit, args.lane_name)
1246
+ repo_paths = {
1247
+ r: str(lane_root / "repos" / r) for r in lane_doc.get("repos", [])
1248
+ }
1249
+
1225
1250
  deduped: list[dict] = []
1226
1251
  seen: set[tuple[str, str]] = set()
1227
1252
  for item in previous:
@@ -1237,6 +1262,7 @@ def enter_lane(args: argparse.Namespace) -> LaneTransitionOutcome:
1237
1262
  "lane_name": args.lane_name,
1238
1263
  "lane_type": lane_doc["lane_type"],
1239
1264
  "repos": lane_doc.get("repos", []),
1265
+ "repo_paths": repo_paths,
1240
1266
  "actor": args.actor,
1241
1267
  "entered_at": now_utc(),
1242
1268
  },
@@ -1270,7 +1296,10 @@ def enter_lane(args: argparse.Namespace) -> LaneTransitionOutcome:
1270
1296
  "timestamp": event["timestamp"],
1271
1297
  },
1272
1298
  )
1273
- return LaneTransitionOutcome("enter", args.owner_unit, previous_lane, args.lane_name, path)
1299
+ return LaneTransitionOutcome(
1300
+ "enter", args.owner_unit, previous_lane, args.lane_name, path,
1301
+ repo_paths=repo_paths,
1302
+ )
1274
1303
 
1275
1304
 
1276
1305
  def exit_lane(args: argparse.Namespace) -> LaneTransitionOutcome:
@@ -11,8 +11,9 @@ name = "gitgrip"
11
11
  # number and it is not derived from Cargo.toml. gr1 releases as crates.io/GitHub
12
12
  # `v1.x.y`; gr2 releases as PyPI `gr2/v2.x.y`. Runtime reads it via
13
13
  # importlib.metadata.version("gitgrip"), never a checked-in file.
14
- version = "2.0.0a1"
15
- description = "gr2 overlay substrate: config-overlay capture, composition, and materialization"
14
+ version = "2.0.0a2"
15
+ description = "Workspace layer for multi-repo work: workspaces, isolated lanes, and one grouped review per slice"
16
+ readme = "README.md"
16
17
  requires-python = ">=3.11"
17
18
  dependencies = [
18
19
  "typer>=0.9",