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.
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/PKG-INFO +12 -3
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/README.md +11 -2
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/PKG-INFO +12 -3
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/SOURCES.txt +14 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/lane_workspace_prototype.py +99 -0
- gitgrip-2.0.0a4/prototypes/repo_maintenance_prototype.py +1372 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/pyproject.toml +2 -2
- gitgrip-2.0.0a4/python_cli/__main__.py +8 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/app.py +450 -59
- gitgrip-2.0.0a4/python_cli/consent.py +437 -0
- gitgrip-2.0.0a4/python_cli/gitinclude.py +198 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/gitops.py +21 -1
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/grip.py +3 -1
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/grip_cli.py +5 -1
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/hooks.py +205 -4
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/migration.py +116 -4
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/spec_apply.py +55 -12
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/syncops.py +6 -1
- gitgrip-2.0.0a4/python_cli/workspace_guidance.py +22 -0
- gitgrip-2.0.0a4/tests/test_cli_adapter_error_boundary.py +226 -0
- gitgrip-2.0.0a4/tests/test_cli_shape_witnesses.py +147 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_event_outcome_policy.py +1 -1
- gitgrip-2.0.0a4/tests/test_first_five_minutes.py +56 -0
- gitgrip-2.0.0a4/tests/test_gitinclude_compiler.py +862 -0
- gitgrip-2.0.0a4/tests/test_gr1_first_run_guidance.py +80 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_hook_events.py +4 -1
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_hook_hardening.py +4 -1
- gitgrip-2.0.0a4/tests/test_hooks_consent.py +859 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_create_fork_base_cli.py +13 -7
- gitgrip-2.0.0a4/tests/test_lane_create_refuses_own_branch.py +231 -0
- gitgrip-2.0.0a4/tests/test_migration_unadopted_notice.py +122 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_projection_tracked_dest.py +4 -4
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_cli.py +1 -1
- gitgrip-2.0.0a4/tests/test_spec_declaration_ref_pin.py +651 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sprint21_sync_platform.py +13 -0
- gitgrip-2.0.0a4/tests/test_submodule_member_predicate.py +440 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_version_static.py +2 -2
- gitgrip-2.0.0a4/tests/test_workspace_convert_clone.py +603 -0
- gitgrip-2.0.0a4/tests/test_workspace_root_defaults.py +147 -0
- gitgrip-2.0.0a2/prototypes/repo_maintenance_prototype.py +0 -659
- gitgrip-2.0.0a2/python_cli/__main__.py +0 -6
- gitgrip-2.0.0a2/tests/test_workspace_convert_clone.py +0 -211
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/dependency_links.txt +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/entry_points.txt +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/requires.txt +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gitgrip.egg-info/top_level.txt +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/__init__.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/__init__.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/activate.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/agent_manifest.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/cli.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/cross_repo.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/drivers.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/introspection.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/language_drivers.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/objects.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/perf.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/refs.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/trust.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/types.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/units.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/overlay/workspace_spec.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2/schemas/gr2-materialization-plan-v1.schema.json +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/gr2_overlay/__init__.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/__init__.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/cache_materialization_probe.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/concurrent_event_stress.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/concurrent_lease_stress.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/concurrent_workspace_cap_stress.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/contribution_protocol.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/cross_mode_lane_stress.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/jsonl_store.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/layout_model_probe.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/propagation_daemon.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/propagation_state_machine.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_exec_playground.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_hook_runtime_playground.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_migration_playground.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_review_checkout_playground.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/python_spec_apply_playground.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/real_git_lane_materialization.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/real_git_playground.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/recall_lane_history.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/prototypes/repo_transport_probe.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/__init__.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/add.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/branch.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/channel_bridge.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/clone_exec.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/commit.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/config.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/env_exec.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/events.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/execops.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/failures.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/file_exec.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/git_review.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/launch_exec.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/merge_verification.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/open_gr_review.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/platform.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/pr.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/project_review.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/prune.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/push.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_dispatch.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_ephemeral.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_rebind.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_run.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/review_runners.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/staging_cleanup.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/target.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/python_cli/workspace_snapshot.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/setup.cfg +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_add.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_agent_manifest_overlay_source.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_app_event_outcomes.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_apply_convergence.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_branch.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_channel_bridge.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_clone_materialization.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_commit.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_config_base_path_guard.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_config_overlay.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_conftest_git_isolation.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_contribution_protocol.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_ensure_lane_checkout_reference_clone.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_env_materialization.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_event_log_integrity.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_events.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_events_torn_line.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_exec_apostrophe_and_oserror.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_exec_single_string_and_materialize_plan.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_execops.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_failure_event_outcome.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_foreground_launch_runtime.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_git_review.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_gr2_packaging.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_gr2_review_receipt.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_cli.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_hardening.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_object_model.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_grip_snapshot.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_jsonl_store.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_lease_show_json.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_lifecycle_safety.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_repo_paths_and_all_skipped.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_lane_toml_serialization.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_launch_primitive.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_m2_overlay_hindsight.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_m2_overlay_mem0.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_m2_overlay_zep.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_materialization_plan_contract.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_merge_evidence.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_merge_parent_verification.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_migration.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_migration_overlay_compatibility.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_no_bare_python_cli_imports.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_null_current_lane_refusal.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_open_gr_enter.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_open_project_refusal_reason_cli.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_acceptance.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_activate.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cli.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cli_wiring.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_composition_merge.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cross_repo_atomic_apply.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cross_repo_perf_gate.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_cross_repo_rollback.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_driver_registry.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_introspection.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_multi_stack.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_object_encoding.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_perf_gates.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_python_driver.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_encoding.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_perf_gates.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_repo_state.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_tier_b_staging_discipline.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_trust_model.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_overlay_workspace_spec.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_pr_events.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_pr_merge_method.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_pr_merge_partial_failure.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_project_file_materialization.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_project_review_range_reconstruction.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_project_review_three_repo.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_propagation_contribution.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_propagation_daemon.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_propagation_state_machine.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_prune.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_push.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_readme_verbs_exist.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_repo_status_linked_worktree.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_repo_status_schema_version.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_repo_status_symlinked_git_dir.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_bind_fork_base.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_bind_from_range.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_bind_verify.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_close_gr.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_create_project_cli.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_dispatch.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_ephemeral.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_open_lane.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_rebind.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_run.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_run_import_isolation.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_run_rerun_and_refusal_receipt.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_runners.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_review_verify_inside.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_rmtree_or_refuse.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_single_repo_cwd_refusal.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_snapshot_id_prefix_resolution.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_spec_apply_event_outcomes.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_staging_cleanup.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_store_verb_rename.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_event_outcomes.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_fast_forward.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_fetch.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_seed_local.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_ssh_rewrite.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_sync_status_probe.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_target.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_tmux_launch_runtime.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_abort.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_apply.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_apply_dry_run.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_manifest_schema.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_propose.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_unit_topological_apply.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_edit_lease_cap.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_identity_boundary.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_init_from_topology.py +0 -0
- {gitgrip-2.0.0a2 → gitgrip-2.0.0a4}/tests/test_workspace_init_local_repos.py +0 -0
- {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.
|
|
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
|
|
31
|
+
pip install --pre gitgrip
|
|
25
32
|
gr2 --version
|
|
26
33
|
```
|
|
27
34
|
|
|
28
|
-
`--pre` is required while
|
|
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
|
|
16
|
+
pip install --pre gitgrip
|
|
10
17
|
gr2 --version
|
|
11
18
|
```
|
|
12
19
|
|
|
13
|
-
`--pre` is required while
|
|
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.
|
|
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
|
|
31
|
+
pip install --pre gitgrip
|
|
25
32
|
gr2 --version
|
|
26
33
|
```
|
|
27
34
|
|
|
28
|
-
`--pre` is required while
|
|
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.
|