gitgrip 2.0.0a2__tar.gz → 2.0.0a4__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 (236) hide show
  1. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/PKG-INFO +12 -3
  2. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/README.md +11 -2
  3. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/PKG-INFO +12 -3
  4. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/SOURCES.txt +14 -0
  5. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/lane_workspace_prototype.py +99 -0
  6. gitgrip-2.0.0a4/prototypes/repo_maintenance_prototype.py +1372 -0
  7. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/pyproject.toml +2 -2
  8. gitgrip-2.0.0a4/python_cli/__main__.py +8 -0
  9. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/app.py +450 -59
  10. gitgrip-2.0.0a4/python_cli/consent.py +437 -0
  11. gitgrip-2.0.0a4/python_cli/gitinclude.py +198 -0
  12. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/gitops.py +21 -1
  13. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/grip.py +3 -1
  14. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/grip_cli.py +5 -1
  15. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/hooks.py +205 -4
  16. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/migration.py +116 -4
  17. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/spec_apply.py +55 -12
  18. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/syncops.py +6 -1
  19. gitgrip-2.0.0a4/python_cli/workspace_guidance.py +22 -0
  20. gitgrip-2.0.0a4/tests/test_cli_adapter_error_boundary.py +226 -0
  21. gitgrip-2.0.0a4/tests/test_cli_shape_witnesses.py +147 -0
  22. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_event_outcome_policy.py +1 -1
  23. gitgrip-2.0.0a4/tests/test_first_five_minutes.py +56 -0
  24. gitgrip-2.0.0a4/tests/test_gitinclude_compiler.py +862 -0
  25. gitgrip-2.0.0a4/tests/test_gr1_first_run_guidance.py +80 -0
  26. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_hook_events.py +4 -1
  27. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_hook_hardening.py +4 -1
  28. gitgrip-2.0.0a4/tests/test_hooks_consent.py +859 -0
  29. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_create_fork_base_cli.py +13 -7
  30. gitgrip-2.0.0a4/tests/test_lane_create_refuses_own_branch.py +231 -0
  31. gitgrip-2.0.0a4/tests/test_migration_unadopted_notice.py +122 -0
  32. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_projection_tracked_dest.py +4 -4
  33. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_cli.py +1 -1
  34. gitgrip-2.0.0a4/tests/test_spec_declaration_ref_pin.py +651 -0
  35. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sprint21_sync_platform.py +13 -0
  36. gitgrip-2.0.0a4/tests/test_submodule_member_predicate.py +440 -0
  37. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_version_static.py +2 -2
  38. gitgrip-2.0.0a4/tests/test_workspace_convert_clone.py +603 -0
  39. gitgrip-2.0.0a4/tests/test_workspace_root_defaults.py +147 -0
  40. gitgrip-2.0.0a2/prototypes/repo_maintenance_prototype.py +0 -659
  41. gitgrip-2.0.0a2/python_cli/__main__.py +0 -6
  42. gitgrip-2.0.0a2/tests/test_workspace_convert_clone.py +0 -211
  43. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/dependency_links.txt +0 -0
  44. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/entry_points.txt +0 -0
  45. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/requires.txt +0 -0
  46. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/top_level.txt +0 -0
  47. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/__init__.py +0 -0
  48. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/__init__.py +0 -0
  49. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/activate.py +0 -0
  50. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/agent_manifest.py +0 -0
  51. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/cli.py +0 -0
  52. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/cross_repo.py +0 -0
  53. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/drivers.py +0 -0
  54. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/introspection.py +0 -0
  55. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/language_drivers.py +0 -0
  56. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/objects.py +0 -0
  57. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/perf.py +0 -0
  58. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/refs.py +0 -0
  59. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/trust.py +0 -0
  60. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/types.py +0 -0
  61. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/units.py +0 -0
  62. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/workspace_spec.py +0 -0
  63. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/schemas/gr2-materialization-plan-v1.schema.json +0 -0
  64. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2_overlay/__init__.py +0 -0
  65. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/__init__.py +0 -0
  66. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/cache_materialization_probe.py +0 -0
  67. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/concurrent_event_stress.py +0 -0
  68. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/concurrent_lease_stress.py +0 -0
  69. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/concurrent_workspace_cap_stress.py +0 -0
  70. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/contribution_protocol.py +0 -0
  71. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/cross_mode_lane_stress.py +0 -0
  72. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/jsonl_store.py +0 -0
  73. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/layout_model_probe.py +0 -0
  74. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/propagation_daemon.py +0 -0
  75. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/propagation_state_machine.py +0 -0
  76. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_exec_playground.py +0 -0
  77. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_hook_runtime_playground.py +0 -0
  78. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_migration_playground.py +0 -0
  79. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_review_checkout_playground.py +0 -0
  80. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_spec_apply_playground.py +0 -0
  81. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/real_git_lane_materialization.py +0 -0
  82. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/real_git_playground.py +0 -0
  83. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/recall_lane_history.py +0 -0
  84. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/repo_transport_probe.py +0 -0
  85. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/__init__.py +0 -0
  86. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/add.py +0 -0
  87. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/branch.py +0 -0
  88. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/channel_bridge.py +0 -0
  89. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/clone_exec.py +0 -0
  90. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/commit.py +0 -0
  91. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/config.py +0 -0
  92. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/env_exec.py +0 -0
  93. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/events.py +0 -0
  94. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/execops.py +0 -0
  95. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/failures.py +0 -0
  96. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/file_exec.py +0 -0
  97. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/git_review.py +0 -0
  98. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/launch_exec.py +0 -0
  99. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/merge_verification.py +0 -0
  100. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/open_gr_review.py +0 -0
  101. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/platform.py +0 -0
  102. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/pr.py +0 -0
  103. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/project_review.py +0 -0
  104. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/prune.py +0 -0
  105. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/push.py +0 -0
  106. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review.py +0 -0
  107. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_dispatch.py +0 -0
  108. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_ephemeral.py +0 -0
  109. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_rebind.py +0 -0
  110. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_run.py +0 -0
  111. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_runners.py +0 -0
  112. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/staging_cleanup.py +0 -0
  113. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/target.py +0 -0
  114. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/workspace_snapshot.py +0 -0
  115. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/setup.cfg +0 -0
  116. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_add.py +0 -0
  117. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_agent_manifest_overlay_source.py +0 -0
  118. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_app_event_outcomes.py +0 -0
  119. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_apply_convergence.py +0 -0
  120. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_branch.py +0 -0
  121. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_channel_bridge.py +0 -0
  122. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_clone_materialization.py +0 -0
  123. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_commit.py +0 -0
  124. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_config_base_path_guard.py +0 -0
  125. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_config_overlay.py +0 -0
  126. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_conftest_git_isolation.py +0 -0
  127. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_contribution_protocol.py +0 -0
  128. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_ensure_lane_checkout_reference_clone.py +0 -0
  129. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_env_materialization.py +0 -0
  130. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_event_log_integrity.py +0 -0
  131. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_events.py +0 -0
  132. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_events_torn_line.py +0 -0
  133. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_exec_apostrophe_and_oserror.py +0 -0
  134. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_exec_single_string_and_materialize_plan.py +0 -0
  135. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_execops.py +0 -0
  136. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_failure_event_outcome.py +0 -0
  137. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_foreground_launch_runtime.py +0 -0
  138. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_git_review.py +0 -0
  139. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_gr2_packaging.py +0 -0
  140. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_gr2_review_receipt.py +0 -0
  141. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_cli.py +0 -0
  142. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_hardening.py +0 -0
  143. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_object_model.py +0 -0
  144. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_snapshot.py +0 -0
  145. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_jsonl_store.py +0 -0
  146. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_lease_show_json.py +0 -0
  147. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_lifecycle_safety.py +0 -0
  148. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_repo_paths_and_all_skipped.py +0 -0
  149. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_toml_serialization.py +0 -0
  150. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_launch_primitive.py +0 -0
  151. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_m2_overlay_hindsight.py +0 -0
  152. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_m2_overlay_mem0.py +0 -0
  153. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_m2_overlay_zep.py +0 -0
  154. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_materialization_plan_contract.py +0 -0
  155. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_merge_evidence.py +0 -0
  156. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_merge_parent_verification.py +0 -0
  157. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_migration.py +0 -0
  158. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_migration_overlay_compatibility.py +0 -0
  159. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_no_bare_python_cli_imports.py +0 -0
  160. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_null_current_lane_refusal.py +0 -0
  161. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_open_gr_enter.py +0 -0
  162. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_open_project_refusal_reason_cli.py +0 -0
  163. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_acceptance.py +0 -0
  164. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_activate.py +0 -0
  165. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cli.py +0 -0
  166. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cli_wiring.py +0 -0
  167. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_composition_merge.py +0 -0
  168. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cross_repo_atomic_apply.py +0 -0
  169. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cross_repo_perf_gate.py +0 -0
  170. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cross_repo_rollback.py +0 -0
  171. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_driver_registry.py +0 -0
  172. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_introspection.py +0 -0
  173. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_multi_stack.py +0 -0
  174. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_object_encoding.py +0 -0
  175. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_perf_gates.py +0 -0
  176. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_python_driver.py +0 -0
  177. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_encoding.py +0 -0
  178. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_perf_gates.py +0 -0
  179. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_repo_state.py +0 -0
  180. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_staging_discipline.py +0 -0
  181. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_trust_model.py +0 -0
  182. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_workspace_spec.py +0 -0
  183. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_pr_events.py +0 -0
  184. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_pr_merge_method.py +0 -0
  185. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_pr_merge_partial_failure.py +0 -0
  186. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_project_file_materialization.py +0 -0
  187. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_project_review_range_reconstruction.py +0 -0
  188. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_project_review_three_repo.py +0 -0
  189. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_propagation_contribution.py +0 -0
  190. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_propagation_daemon.py +0 -0
  191. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_propagation_state_machine.py +0 -0
  192. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_prune.py +0 -0
  193. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_push.py +0 -0
  194. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_readme_verbs_exist.py +0 -0
  195. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_repo_status_linked_worktree.py +0 -0
  196. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_repo_status_schema_version.py +0 -0
  197. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_repo_status_symlinked_git_dir.py +0 -0
  198. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_bind_fork_base.py +0 -0
  199. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_bind_from_range.py +0 -0
  200. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_bind_verify.py +0 -0
  201. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_close_gr.py +0 -0
  202. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_create_project_cli.py +0 -0
  203. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_dispatch.py +0 -0
  204. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_ephemeral.py +0 -0
  205. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_open_lane.py +0 -0
  206. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_rebind.py +0 -0
  207. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_run.py +0 -0
  208. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_run_import_isolation.py +0 -0
  209. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_run_rerun_and_refusal_receipt.py +0 -0
  210. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_runners.py +0 -0
  211. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_verify_inside.py +0 -0
  212. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_rmtree_or_refuse.py +0 -0
  213. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_single_repo_cwd_refusal.py +0 -0
  214. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_snapshot_id_prefix_resolution.py +0 -0
  215. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_spec_apply_event_outcomes.py +0 -0
  216. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_staging_cleanup.py +0 -0
  217. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_store_verb_rename.py +0 -0
  218. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_event_outcomes.py +0 -0
  219. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_fast_forward.py +0 -0
  220. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_fetch.py +0 -0
  221. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_seed_local.py +0 -0
  222. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_ssh_rewrite.py +0 -0
  223. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_status_probe.py +0 -0
  224. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_target.py +0 -0
  225. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_tmux_launch_runtime.py +0 -0
  226. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_abort.py +0 -0
  227. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_apply.py +0 -0
  228. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_apply_dry_run.py +0 -0
  229. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_manifest_schema.py +0 -0
  230. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_propose.py +0 -0
  231. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_topological_apply.py +0 -0
  232. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_edit_lease_cap.py +0 -0
  233. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_identity_boundary.py +0 -0
  234. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_init_from_topology.py +0 -0
  235. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_init_local_repos.py +0 -0
  236. {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_snapshot.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitgrip
3
- Version: 2.0.0a2
3
+ Version: 2.0.0a4
4
4
  Summary: Workspace layer for multi-repo work: workspaces, isolated lanes, and one grouped review per slice
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -19,13 +19,22 @@ Requires-Dist: ruff>=0.4; extra == "dev"
19
19
 
20
20
  ## Install
21
21
 
22
+ ```bash
23
+ uv tool install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
24
+ gr2 --version
25
+ ```
26
+
27
+ Without uv, a venv and pip do the same:
28
+
22
29
  ```bash
23
30
  python3 -m venv ~/gr2-venv && source ~/gr2-venv/bin/activate
24
- pip install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
31
+ pip install --pre gitgrip
25
32
  gr2 --version
26
33
  ```
27
34
 
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.
35
+ `--pre` is required while every gr2 release is an alpha: 1.5.0 and 1.5.1 were pre-alpha builds and are yanked, so without `--pre` there is nothing to install.
36
+
37
+ Already installed 1.5.0 or 1.5.1? The install commands above leave it in place, because an installed version already satisfies them. Upgrade explicitly: `uv tool upgrade --prerelease allow gitgrip`, or `pip install --pre -U gitgrip`. To run unreleased development code instead, install from a checkout: `pip install -e gr2/` from the repository root.
29
38
 
30
39
  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
40
 
@@ -4,13 +4,22 @@
4
4
 
5
5
  ## Install
6
6
 
7
+ ```bash
8
+ uv tool install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
9
+ gr2 --version
10
+ ```
11
+
12
+ Without uv, a venv and pip do the same:
13
+
7
14
  ```bash
8
15
  python3 -m venv ~/gr2-venv && source ~/gr2-venv/bin/activate
9
- pip install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
16
+ pip install --pre gitgrip
10
17
  gr2 --version
11
18
  ```
12
19
 
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.
20
+ `--pre` is required while every gr2 release is an alpha: 1.5.0 and 1.5.1 were pre-alpha builds and are yanked, so without `--pre` there is nothing to install.
21
+
22
+ Already installed 1.5.0 or 1.5.1? The install commands above leave it in place, because an installed version already satisfies them. Upgrade explicitly: `uv tool upgrade --prerelease allow gitgrip`, or `pip install --pre -U gitgrip`. To run unreleased development code instead, install from a checkout: `pip install -e gr2/` from the repository root.
14
23
 
15
24
  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
25
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitgrip
3
- Version: 2.0.0a2
3
+ Version: 2.0.0a4
4
4
  Summary: Workspace layer for multi-repo work: workspaces, isolated lanes, and one grouped review per slice
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -19,13 +19,22 @@ Requires-Dist: ruff>=0.4; extra == "dev"
19
19
 
20
20
  ## Install
21
21
 
22
+ ```bash
23
+ uv tool install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
24
+ gr2 --version
25
+ ```
26
+
27
+ Without uv, a venv and pip do the same:
28
+
22
29
  ```bash
23
30
  python3 -m venv ~/gr2-venv && source ~/gr2-venv/bin/activate
24
- pip install --pre gitgrip # the PyPI package is "gitgrip"; the command is "gr2"
31
+ pip install --pre gitgrip
25
32
  gr2 --version
26
33
  ```
27
34
 
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.
35
+ `--pre` is required while every gr2 release is an alpha: 1.5.0 and 1.5.1 were pre-alpha builds and are yanked, so without `--pre` there is nothing to install.
36
+
37
+ Already installed 1.5.0 or 1.5.1? The install commands above leave it in place, because an installed version already satisfies them. Upgrade explicitly: `uv tool upgrade --prerelease allow gitgrip`, or `pip install --pre -U gitgrip`. To run unreleased development code instead, install from a checkout: `pip install -e gr2/` from the repository root.
29
38
 
30
39
  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
40
 
@@ -55,12 +55,14 @@ python_cli/channel_bridge.py
55
55
  python_cli/clone_exec.py
56
56
  python_cli/commit.py
57
57
  python_cli/config.py
58
+ python_cli/consent.py
58
59
  python_cli/env_exec.py
59
60
  python_cli/events.py
60
61
  python_cli/execops.py
61
62
  python_cli/failures.py
62
63
  python_cli/file_exec.py
63
64
  python_cli/git_review.py
65
+ python_cli/gitinclude.py
64
66
  python_cli/gitops.py
65
67
  python_cli/grip.py
66
68
  python_cli/grip_cli.py
@@ -84,6 +86,7 @@ python_cli/spec_apply.py
84
86
  python_cli/staging_cleanup.py
85
87
  python_cli/syncops.py
86
88
  python_cli/target.py
89
+ python_cli/workspace_guidance.py
87
90
  python_cli/workspace_snapshot.py
88
91
  tests/test_add.py
89
92
  tests/test_agent_manifest_overlay_source.py
@@ -91,6 +94,8 @@ tests/test_app_event_outcomes.py
91
94
  tests/test_apply_convergence.py
92
95
  tests/test_branch.py
93
96
  tests/test_channel_bridge.py
97
+ tests/test_cli_adapter_error_boundary.py
98
+ tests/test_cli_shape_witnesses.py
94
99
  tests/test_clone_materialization.py
95
100
  tests/test_commit.py
96
101
  tests/test_config_base_path_guard.py
@@ -107,8 +112,11 @@ tests/test_exec_apostrophe_and_oserror.py
107
112
  tests/test_exec_single_string_and_materialize_plan.py
108
113
  tests/test_execops.py
109
114
  tests/test_failure_event_outcome.py
115
+ tests/test_first_five_minutes.py
110
116
  tests/test_foreground_launch_runtime.py
111
117
  tests/test_git_review.py
118
+ tests/test_gitinclude_compiler.py
119
+ tests/test_gr1_first_run_guidance.py
112
120
  tests/test_gr2_packaging.py
113
121
  tests/test_gr2_review_receipt.py
114
122
  tests/test_grip_cli.py
@@ -117,8 +125,10 @@ tests/test_grip_object_model.py
117
125
  tests/test_grip_snapshot.py
118
126
  tests/test_hook_events.py
119
127
  tests/test_hook_hardening.py
128
+ tests/test_hooks_consent.py
120
129
  tests/test_jsonl_store.py
121
130
  tests/test_lane_create_fork_base_cli.py
131
+ tests/test_lane_create_refuses_own_branch.py
122
132
  tests/test_lane_lease_show_json.py
123
133
  tests/test_lane_lifecycle_safety.py
124
134
  tests/test_lane_repo_paths_and_all_skipped.py
@@ -132,6 +142,7 @@ tests/test_merge_evidence.py
132
142
  tests/test_merge_parent_verification.py
133
143
  tests/test_migration.py
134
144
  tests/test_migration_overlay_compatibility.py
145
+ tests/test_migration_unadopted_notice.py
135
146
  tests/test_no_bare_python_cli_imports.py
136
147
  tests/test_null_current_lane_refusal.py
137
148
  tests/test_open_gr_enter.py
@@ -191,9 +202,11 @@ tests/test_rmtree_or_refuse.py
191
202
  tests/test_single_repo_cwd_refusal.py
192
203
  tests/test_snapshot_id_prefix_resolution.py
193
204
  tests/test_spec_apply_event_outcomes.py
205
+ tests/test_spec_declaration_ref_pin.py
194
206
  tests/test_sprint21_sync_platform.py
195
207
  tests/test_staging_cleanup.py
196
208
  tests/test_store_verb_rename.py
209
+ tests/test_submodule_member_predicate.py
197
210
  tests/test_sync_event_outcomes.py
198
211
  tests/test_sync_fast_forward.py
199
212
  tests/test_sync_fetch.py
@@ -214,4 +227,5 @@ tests/test_workspace_edit_lease_cap.py
214
227
  tests/test_workspace_identity_boundary.py
215
228
  tests/test_workspace_init_from_topology.py
216
229
  tests/test_workspace_init_local_repos.py
230
+ tests/test_workspace_root_defaults.py
217
231
  tests/test_workspace_snapshot.py
@@ -923,6 +923,97 @@ def _validate_bound_worktree(bind_path: Path, workspace_root: Path) -> tuple[str
923
923
  return head, branch
924
924
 
925
925
 
926
+ #: How long the origin may take to report its default branch before the answer is
927
+ #: "cannot tell". Generous for a symref read, and short enough that an origin which
928
+ #: accepts and never replies cannot block `lane create` with no output. Without it,
929
+ #: an offline laptop or a blackholed origin hangs the verb where it used to create a
930
+ #: lane without any network call at all.
931
+ _LS_REMOTE_TIMEOUT_SECONDS = 5.0
932
+
933
+
934
+ def _origin_default_branch(repo_path: Path, url: str | None = None) -> str | None:
935
+ """The repo's integration branch, or None when it cannot be determined.
936
+
937
+ A clone records it as `origin/HEAD`. That symref is ABSENT in a clone made
938
+ before the remote had any refs — which is the normal state of a repo cloned
939
+ empty and pushed later, and it is exactly the state in which a lane created on
940
+ the default branch looks harmless. So when the local record is missing, ask the
941
+ origin itself (`ls-remote --symref`), which is the same remote the lane is about
942
+ to clone from anyway. A remote that cannot be reached gives None: "cannot tell"
943
+ is never allowed to become a refusal. Unreachable includes UNANSWERED — the call
944
+ is bounded, and an expiry is None on the same channel as any other git failure
945
+ rather than an exception the caller has to remember to catch separately.
946
+ """
947
+ proc = gitops.git(repo_path, "rev-parse", "--abbrev-ref", "origin/HEAD")
948
+ if proc.returncode == 0:
949
+ ref = proc.stdout.strip()
950
+ if ref.startswith("origin/"):
951
+ return ref.split("/", 1)[1]
952
+ if not url:
953
+ return None
954
+ remote = gitops.git(
955
+ repo_path, "ls-remote", "--symref", url, "HEAD", timeout=_LS_REMOTE_TIMEOUT_SECONDS
956
+ )
957
+ if remote.returncode != 0:
958
+ # A git that never returned is the same answer as a git that refused:
959
+ # "cannot tell". The bound above is what makes that reachable at all — an
960
+ # origin that accepts and says nothing used to block the verb outright.
961
+ return None
962
+ for line in remote.stdout.splitlines():
963
+ if line.startswith("ref:") and line.rstrip().endswith("HEAD"):
964
+ ref = line.split()[1]
965
+ # Strip the PREFIX, never split on every slash: a default branch whose
966
+ # name contains one (`release/1.x`) came back as its last segment, so the
967
+ # guard compared the requested branch against a string the origin never
968
+ # reported and the no-isolation lane was created in silence.
969
+ if not ref.startswith("refs/heads/"):
970
+ return None
971
+ return ref.removeprefix("refs/heads/")
972
+ return None
973
+
974
+
975
+ def _lane_branch_refusal(workspace_root: Path, spec: dict, repo: str, branch: str) -> str | None:
976
+ """The one sentence that refuses a lane branch with no isolation, or None.
977
+
978
+ A lane is the isolation primitive. A lane whose branch IS the repository's own
979
+ branch has no isolation at all: work committed there and pushed with `gr2 push`
980
+ lands on the branch the lane was supposed to be forked from, and the first
981
+ refusal arrived at `pr create` — after the remote had already been written
982
+ (measured on the released 2.0.0a2: `lane create --branch main`, push exit 0
983
+ "Pushed main", then `pr create` exit 1 "head branch main is the same as base
984
+ branch main"). Nothing refused at the point the choice was made.
985
+
986
+ The comparison is against what is CHECKED OUT here and what the origin says its
987
+ default is. A repo with no local checkout, or one whose origin cannot be
988
+ reached, is skipped rather than refused: this guard may not invent a conflict it
989
+ cannot see.
990
+ """
991
+ entry = next((row for row in spec.get("repos", []) if row.get("name") == repo), None)
992
+ if entry is None:
993
+ return None
994
+ rel = entry.get("path")
995
+ if not rel:
996
+ return None
997
+ checkout = workspace_root / str(rel)
998
+ if not gitops.is_git_repo(checkout):
999
+ return None
1000
+ matched: str | None = None
1001
+ if branch == gitops.current_branch(checkout):
1002
+ matched = f"the branch checked out at {rel}"
1003
+ else:
1004
+ default = _origin_default_branch(checkout, str(entry.get("url") or "") or None)
1005
+ if default and branch == default:
1006
+ matched = f"the repo's integration branch ({default})"
1007
+ if matched is None:
1008
+ return None
1009
+ return (
1010
+ f"lane branch '{branch}' for repo '{repo}' is {matched}: a lane forked from the branch it will "
1011
+ f"land on has no isolation, and a push would go straight to '{branch}'. Pass a lane branch that is "
1012
+ f"neither the repo's checked-out nor its integration branch (e.g. feat/<name>), or use --bind to "
1013
+ f"label an existing worktree."
1014
+ )
1015
+
1016
+
926
1017
  def create_lane(args: argparse.Namespace) -> int:
927
1018
  workspace_root = args.workspace_root.resolve()
928
1019
  validate_lane_path_component(args.owner_unit, "owner_unit")
@@ -963,6 +1054,14 @@ def create_lane(args: argparse.Namespace) -> int:
963
1054
  branch_map = {repos[0]: branch}
964
1055
  else:
965
1056
  branch_map = parse_branch_arg(args.branch, repos)
1057
+ # A materialized lane's branch may not be the repo's own branch: the lane
1058
+ # would have no isolation and its push would land on the integration
1059
+ # branch. Refused HERE, where the choice is made, rather than at the first
1060
+ # `pr create` after the remote had been written.
1061
+ for _repo in repos:
1062
+ refusal = _lane_branch_refusal(workspace_root, spec, _repo, branch_map[_repo])
1063
+ if refusal:
1064
+ raise SystemExit(refusal)
966
1065
 
967
1066
  # Fork base: record what the caller supplies, do not derive.
968
1067
  # Each entry names a repo IN the lane and carries a 40-hex integration-branch tip.