gitgrip 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. gitgrip-1.5.0/MANIFEST.in +6 -0
  2. gitgrip-1.5.0/PKG-INFO +13 -0
  3. gitgrip-1.5.0/README.md +258 -0
  4. gitgrip-1.5.0/VERSION +1 -0
  5. gitgrip-1.5.0/_build/__pycache__/backend.cpython-311.pyc +0 -0
  6. gitgrip-1.5.0/_build/__pycache__/version_from_cargo.cpython-311.pyc +0 -0
  7. gitgrip-1.5.0/_build/backend.py +58 -0
  8. gitgrip-1.5.0/_build/version_from_cargo.py +43 -0
  9. gitgrip-1.5.0/gitgrip.egg-info/PKG-INFO +13 -0
  10. gitgrip-1.5.0/gitgrip.egg-info/SOURCES.txt +199 -0
  11. gitgrip-1.5.0/gitgrip.egg-info/dependency_links.txt +1 -0
  12. gitgrip-1.5.0/gitgrip.egg-info/entry_points.txt +2 -0
  13. gitgrip-1.5.0/gitgrip.egg-info/requires.txt +9 -0
  14. gitgrip-1.5.0/gitgrip.egg-info/top_level.txt +2 -0
  15. gitgrip-1.5.0/gr2/__init__.py +0 -0
  16. gitgrip-1.5.0/gr2/overlay/__init__.py +6 -0
  17. gitgrip-1.5.0/gr2/overlay/activate.py +196 -0
  18. gitgrip-1.5.0/gr2/overlay/agent_manifest.py +138 -0
  19. gitgrip-1.5.0/gr2/overlay/cli.py +181 -0
  20. gitgrip-1.5.0/gr2/overlay/cross_repo.py +124 -0
  21. gitgrip-1.5.0/gr2/overlay/drivers.py +113 -0
  22. gitgrip-1.5.0/gr2/overlay/introspection.py +155 -0
  23. gitgrip-1.5.0/gr2/overlay/language_drivers.py +115 -0
  24. gitgrip-1.5.0/gr2/overlay/objects.py +412 -0
  25. gitgrip-1.5.0/gr2/overlay/perf.py +251 -0
  26. gitgrip-1.5.0/gr2/overlay/refs.py +36 -0
  27. gitgrip-1.5.0/gr2/overlay/trust.py +150 -0
  28. gitgrip-1.5.0/gr2/overlay/types.py +69 -0
  29. gitgrip-1.5.0/gr2/overlay/units.py +313 -0
  30. gitgrip-1.5.0/gr2/overlay/workspace_spec.py +59 -0
  31. gitgrip-1.5.0/gr2/schemas/gr2-materialization-plan-v1.schema.json +191 -0
  32. gitgrip-1.5.0/gr2_overlay/__init__.py +37 -0
  33. gitgrip-1.5.0/prototypes/__init__.py +0 -0
  34. gitgrip-1.5.0/prototypes/cache_materialization_probe.py +190 -0
  35. gitgrip-1.5.0/prototypes/concurrent_event_stress.py +199 -0
  36. gitgrip-1.5.0/prototypes/concurrent_lease_stress.py +240 -0
  37. gitgrip-1.5.0/prototypes/concurrent_workspace_cap_stress.py +231 -0
  38. gitgrip-1.5.0/prototypes/contribution_protocol.py +665 -0
  39. gitgrip-1.5.0/prototypes/cross_mode_lane_stress.py +986 -0
  40. gitgrip-1.5.0/prototypes/jsonl_store.py +158 -0
  41. gitgrip-1.5.0/prototypes/lane_workspace_prototype.py +2088 -0
  42. gitgrip-1.5.0/prototypes/layout_model_probe.py +139 -0
  43. gitgrip-1.5.0/prototypes/propagation_daemon.py +546 -0
  44. gitgrip-1.5.0/prototypes/propagation_state_machine.py +1478 -0
  45. gitgrip-1.5.0/prototypes/python_exec_playground.py +194 -0
  46. gitgrip-1.5.0/prototypes/python_hook_runtime_playground.py +240 -0
  47. gitgrip-1.5.0/prototypes/python_migration_playground.py +144 -0
  48. gitgrip-1.5.0/prototypes/python_review_checkout_playground.py +242 -0
  49. gitgrip-1.5.0/prototypes/python_spec_apply_playground.py +282 -0
  50. gitgrip-1.5.0/prototypes/real_git_lane_materialization.py +248 -0
  51. gitgrip-1.5.0/prototypes/real_git_playground.py +334 -0
  52. gitgrip-1.5.0/prototypes/recall_lane_history.py +274 -0
  53. gitgrip-1.5.0/prototypes/repo_maintenance_prototype.py +659 -0
  54. gitgrip-1.5.0/prototypes/repo_transport_probe.py +147 -0
  55. gitgrip-1.5.0/pyproject.toml +72 -0
  56. gitgrip-1.5.0/python_cli/__init__.py +2 -0
  57. gitgrip-1.5.0/python_cli/__main__.py +6 -0
  58. gitgrip-1.5.0/python_cli/add.py +51 -0
  59. gitgrip-1.5.0/python_cli/app.py +2516 -0
  60. gitgrip-1.5.0/python_cli/branch.py +67 -0
  61. gitgrip-1.5.0/python_cli/channel_bridge.py +131 -0
  62. gitgrip-1.5.0/python_cli/clone_exec.py +1019 -0
  63. gitgrip-1.5.0/python_cli/commit.py +199 -0
  64. gitgrip-1.5.0/python_cli/config.py +291 -0
  65. gitgrip-1.5.0/python_cli/env_exec.py +419 -0
  66. gitgrip-1.5.0/python_cli/events.py +529 -0
  67. gitgrip-1.5.0/python_cli/execops.py +372 -0
  68. gitgrip-1.5.0/python_cli/failures.py +98 -0
  69. gitgrip-1.5.0/python_cli/file_exec.py +256 -0
  70. gitgrip-1.5.0/python_cli/gitops.py +226 -0
  71. gitgrip-1.5.0/python_cli/grip.py +1337 -0
  72. gitgrip-1.5.0/python_cli/grip_cli.py +493 -0
  73. gitgrip-1.5.0/python_cli/hooks.py +450 -0
  74. gitgrip-1.5.0/python_cli/launch_exec.py +786 -0
  75. gitgrip-1.5.0/python_cli/merge_verification.py +274 -0
  76. gitgrip-1.5.0/python_cli/migration.py +985 -0
  77. gitgrip-1.5.0/python_cli/open_gr_review.py +699 -0
  78. gitgrip-1.5.0/python_cli/platform.py +441 -0
  79. gitgrip-1.5.0/python_cli/pr.py +487 -0
  80. gitgrip-1.5.0/python_cli/project_review.py +314 -0
  81. gitgrip-1.5.0/python_cli/prune.py +365 -0
  82. gitgrip-1.5.0/python_cli/push.py +172 -0
  83. gitgrip-1.5.0/python_cli/review.py +462 -0
  84. gitgrip-1.5.0/python_cli/review_ephemeral.py +143 -0
  85. gitgrip-1.5.0/python_cli/review_run.py +621 -0
  86. gitgrip-1.5.0/python_cli/spec_apply.py +1285 -0
  87. gitgrip-1.5.0/python_cli/staging_cleanup.py +205 -0
  88. gitgrip-1.5.0/python_cli/syncops.py +920 -0
  89. gitgrip-1.5.0/python_cli/target.py +100 -0
  90. gitgrip-1.5.0/python_cli/workspace_snapshot.py +105 -0
  91. gitgrip-1.5.0/setup.cfg +4 -0
  92. gitgrip-1.5.0/tests/test_add.py +129 -0
  93. gitgrip-1.5.0/tests/test_agent_manifest_overlay_source.py +171 -0
  94. gitgrip-1.5.0/tests/test_app_event_outcomes.py +76 -0
  95. gitgrip-1.5.0/tests/test_apply_convergence.py +286 -0
  96. gitgrip-1.5.0/tests/test_branch.py +169 -0
  97. gitgrip-1.5.0/tests/test_channel_bridge.py +333 -0
  98. gitgrip-1.5.0/tests/test_clone_materialization.py +1013 -0
  99. gitgrip-1.5.0/tests/test_commit.py +305 -0
  100. gitgrip-1.5.0/tests/test_config_base_path_guard.py +64 -0
  101. gitgrip-1.5.0/tests/test_config_overlay.py +508 -0
  102. gitgrip-1.5.0/tests/test_contribution_protocol.py +723 -0
  103. gitgrip-1.5.0/tests/test_ensure_lane_checkout_reference_clone.py +360 -0
  104. gitgrip-1.5.0/tests/test_env_materialization.py +375 -0
  105. gitgrip-1.5.0/tests/test_event_log_integrity.py +252 -0
  106. gitgrip-1.5.0/tests/test_event_outcome_policy.py +149 -0
  107. gitgrip-1.5.0/tests/test_events.py +540 -0
  108. gitgrip-1.5.0/tests/test_events_torn_line.py +592 -0
  109. gitgrip-1.5.0/tests/test_execops.py +342 -0
  110. gitgrip-1.5.0/tests/test_failure_event_outcome.py +36 -0
  111. gitgrip-1.5.0/tests/test_gr2_packaging.py +131 -0
  112. gitgrip-1.5.0/tests/test_gr2_review_receipt.py +172 -0
  113. gitgrip-1.5.0/tests/test_grip_cli.py +536 -0
  114. gitgrip-1.5.0/tests/test_grip_hardening.py +270 -0
  115. gitgrip-1.5.0/tests/test_grip_object_model.py +357 -0
  116. gitgrip-1.5.0/tests/test_grip_snapshot.py +472 -0
  117. gitgrip-1.5.0/tests/test_hook_events.py +377 -0
  118. gitgrip-1.5.0/tests/test_hook_hardening.py +417 -0
  119. gitgrip-1.5.0/tests/test_jsonl_store.py +239 -0
  120. gitgrip-1.5.0/tests/test_lane_create_fork_base_cli.py +203 -0
  121. gitgrip-1.5.0/tests/test_lane_lease_show_json.py +47 -0
  122. gitgrip-1.5.0/tests/test_lane_lifecycle_safety.py +677 -0
  123. gitgrip-1.5.0/tests/test_lane_toml_serialization.py +285 -0
  124. gitgrip-1.5.0/tests/test_launch_primitive.py +377 -0
  125. gitgrip-1.5.0/tests/test_m2_overlay_hindsight.py +196 -0
  126. gitgrip-1.5.0/tests/test_m2_overlay_mem0.py +193 -0
  127. gitgrip-1.5.0/tests/test_m2_overlay_zep.py +195 -0
  128. gitgrip-1.5.0/tests/test_materialization_plan_contract.py +1520 -0
  129. gitgrip-1.5.0/tests/test_merge_evidence.py +245 -0
  130. gitgrip-1.5.0/tests/test_merge_parent_verification.py +395 -0
  131. gitgrip-1.5.0/tests/test_migration.py +1112 -0
  132. gitgrip-1.5.0/tests/test_migration_overlay_compatibility.py +186 -0
  133. gitgrip-1.5.0/tests/test_no_bare_python_cli_imports.py +94 -0
  134. gitgrip-1.5.0/tests/test_null_current_lane_refusal.py +146 -0
  135. gitgrip-1.5.0/tests/test_open_gr_enter.py +650 -0
  136. gitgrip-1.5.0/tests/test_open_project_refusal_reason_cli.py +54 -0
  137. gitgrip-1.5.0/tests/test_overlay_acceptance.py +308 -0
  138. gitgrip-1.5.0/tests/test_overlay_activate.py +299 -0
  139. gitgrip-1.5.0/tests/test_overlay_cli.py +75 -0
  140. gitgrip-1.5.0/tests/test_overlay_cli_wiring.py +299 -0
  141. gitgrip-1.5.0/tests/test_overlay_composition_merge.py +202 -0
  142. gitgrip-1.5.0/tests/test_overlay_cross_repo_atomic_apply.py +176 -0
  143. gitgrip-1.5.0/tests/test_overlay_cross_repo_perf_gate.py +88 -0
  144. gitgrip-1.5.0/tests/test_overlay_cross_repo_rollback.py +219 -0
  145. gitgrip-1.5.0/tests/test_overlay_driver_registry.py +179 -0
  146. gitgrip-1.5.0/tests/test_overlay_introspection.py +223 -0
  147. gitgrip-1.5.0/tests/test_overlay_multi_stack.py +273 -0
  148. gitgrip-1.5.0/tests/test_overlay_object_encoding.py +189 -0
  149. gitgrip-1.5.0/tests/test_overlay_perf_gates.py +125 -0
  150. gitgrip-1.5.0/tests/test_overlay_python_driver.py +94 -0
  151. gitgrip-1.5.0/tests/test_overlay_tier_b_encoding.py +261 -0
  152. gitgrip-1.5.0/tests/test_overlay_tier_b_perf_gates.py +78 -0
  153. gitgrip-1.5.0/tests/test_overlay_tier_b_repo_state.py +203 -0
  154. gitgrip-1.5.0/tests/test_overlay_tier_b_staging_discipline.py +178 -0
  155. gitgrip-1.5.0/tests/test_overlay_trust_model.py +223 -0
  156. gitgrip-1.5.0/tests/test_overlay_workspace_spec.py +156 -0
  157. gitgrip-1.5.0/tests/test_pr_events.py +611 -0
  158. gitgrip-1.5.0/tests/test_pr_merge_method.py +80 -0
  159. gitgrip-1.5.0/tests/test_pr_merge_partial_failure.py +214 -0
  160. gitgrip-1.5.0/tests/test_project_file_materialization.py +442 -0
  161. gitgrip-1.5.0/tests/test_project_review_range_reconstruction.py +278 -0
  162. gitgrip-1.5.0/tests/test_project_review_three_repo.py +490 -0
  163. gitgrip-1.5.0/tests/test_propagation_contribution.py +420 -0
  164. gitgrip-1.5.0/tests/test_propagation_daemon.py +849 -0
  165. gitgrip-1.5.0/tests/test_propagation_state_machine.py +990 -0
  166. gitgrip-1.5.0/tests/test_prune.py +375 -0
  167. gitgrip-1.5.0/tests/test_push.py +318 -0
  168. gitgrip-1.5.0/tests/test_repo_status_linked_worktree.py +117 -0
  169. gitgrip-1.5.0/tests/test_repo_status_schema_version.py +69 -0
  170. gitgrip-1.5.0/tests/test_repo_status_symlinked_git_dir.py +103 -0
  171. gitgrip-1.5.0/tests/test_review_bind_fork_base.py +135 -0
  172. gitgrip-1.5.0/tests/test_review_bind_from_range.py +164 -0
  173. gitgrip-1.5.0/tests/test_review_bind_verify.py +310 -0
  174. gitgrip-1.5.0/tests/test_review_cli.py +435 -0
  175. gitgrip-1.5.0/tests/test_review_close_gr.py +296 -0
  176. gitgrip-1.5.0/tests/test_review_create_project_cli.py +61 -0
  177. gitgrip-1.5.0/tests/test_review_ephemeral.py +121 -0
  178. gitgrip-1.5.0/tests/test_review_open_lane.py +553 -0
  179. gitgrip-1.5.0/tests/test_review_run.py +646 -0
  180. gitgrip-1.5.0/tests/test_review_verify_inside.py +635 -0
  181. gitgrip-1.5.0/tests/test_rmtree_or_refuse.py +513 -0
  182. gitgrip-1.5.0/tests/test_snapshot_id_prefix_resolution.py +132 -0
  183. gitgrip-1.5.0/tests/test_spec_apply_event_outcomes.py +46 -0
  184. gitgrip-1.5.0/tests/test_sprint21_sync_platform.py +1094 -0
  185. gitgrip-1.5.0/tests/test_staging_cleanup.py +422 -0
  186. gitgrip-1.5.0/tests/test_sync_event_outcomes.py +104 -0
  187. gitgrip-1.5.0/tests/test_sync_fetch.py +402 -0
  188. gitgrip-1.5.0/tests/test_target.py +218 -0
  189. gitgrip-1.5.0/tests/test_tmux_launch_runtime.py +764 -0
  190. gitgrip-1.5.0/tests/test_unit_abort.py +117 -0
  191. gitgrip-1.5.0/tests/test_unit_apply.py +142 -0
  192. gitgrip-1.5.0/tests/test_unit_apply_dry_run.py +115 -0
  193. gitgrip-1.5.0/tests/test_unit_manifest_schema.py +265 -0
  194. gitgrip-1.5.0/tests/test_unit_propose.py +192 -0
  195. gitgrip-1.5.0/tests/test_unit_topological_apply.py +100 -0
  196. gitgrip-1.5.0/tests/test_version_single_sourced.py +96 -0
  197. gitgrip-1.5.0/tests/test_workspace_convert_clone.py +211 -0
  198. gitgrip-1.5.0/tests/test_workspace_edit_lease_cap.py +28 -0
  199. gitgrip-1.5.0/tests/test_workspace_identity_boundary.py +183 -0
  200. gitgrip-1.5.0/tests/test_workspace_init_from_topology.py +274 -0
  201. gitgrip-1.5.0/tests/test_workspace_snapshot.py +302 -0
@@ -0,0 +1,6 @@
1
+ # VERSION is generated at build time from ../Cargo.toml; carry it into the sdist
2
+ # so a wheel built FROM the sdist (where Cargo.toml is absent) can read it.
3
+ include VERSION
4
+ # The in-tree build backend must travel in the sdist, or `build_wheel` from an
5
+ # unpacked sdist cannot find backend-path=["_build"].
6
+ graft _build
gitgrip-1.5.0/PKG-INFO ADDED
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitgrip
3
+ Version: 1.5.0
4
+ Summary: gr2 overlay substrate: config-overlay capture, composition, and materialization
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: typer>=0.9
7
+ Requires-Dist: tomli_w>=1.0
8
+ Requires-Dist: pyyaml>=6.0
9
+ Requires-Dist: toml>=0.10
10
+ Requires-Dist: jsonschema>=4.18
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=8.0; extra == "dev"
13
+ Requires-Dist: ruff>=0.4; extra == "dev"
@@ -0,0 +1,258 @@
1
+ # gr2 overlay substrate
2
+
3
+ Config-overlay capture, composition, and materialization for gitgrip
4
+ workspaces. Overlays are git-native objects that layer configuration
5
+ files on top of a workspace without modifying the base branch.
6
+
7
+ ## What is an overlay?
8
+
9
+ An overlay is a set of Tier A config files (`.toml`, `.yml`, `.json`,
10
+ `COMPOSE.md`) captured as an annotated git tag pointing at a structured
11
+ tree. Overlays live in `refs/overlays/<author>/<name>` and can be pushed,
12
+ fetched, and activated across machines using standard git transport.
13
+
14
+ When activated, an overlay eagerly materializes its files into the
15
+ workspace. When deactivated, those files are removed and the workspace
16
+ returns to its pre-overlay state.
17
+
18
+ ## Quick start
19
+
20
+ Create your first overlay in under 3 minutes.
21
+
22
+ ### 1. Set up stores
23
+
24
+ ```python
25
+ from pathlib import Path
26
+ from gr2.overlay.objects import capture_overlay_object
27
+ from gr2.overlay.activate import activate_overlay, deactivate_overlay
28
+ from gr2.overlay.types import OverlayMeta, OverlayRef, OverlayTier, TrustLevel
29
+
30
+ # Initialize a bare git repo as the overlay store
31
+ import subprocess
32
+ store = Path("overlay-store.git")
33
+ subprocess.run(["git", "init", "--bare", str(store)], check=True)
34
+ ```
35
+
36
+ ### 2. Capture an overlay
37
+
38
+ ```python
39
+ # Create source config files
40
+ source = Path("my-overlay-source")
41
+ source.mkdir(exist_ok=True)
42
+ (source / "settings.toml").write_text('[ui]\ntheme = "dark"\n')
43
+ (source / "COMPOSE.md").write_text("# My Overlay\n")
44
+
45
+ # Capture into the store
46
+ ref = OverlayRef(author="myteam", name="dark-theme")
47
+ meta = OverlayMeta(
48
+ ref=ref,
49
+ tier=OverlayTier.A,
50
+ trust=TrustLevel.TRUSTED,
51
+ author="myteam",
52
+ timestamp="2026-05-01T00:00:00Z",
53
+ )
54
+ capture_overlay_object(store, source, meta)
55
+ ```
56
+
57
+ ### 3. Activate in a workspace
58
+
59
+ ```python
60
+ workspace = Path("my-workspace")
61
+ workspace.mkdir(exist_ok=True)
62
+
63
+ result = activate_overlay(
64
+ workspace_root=workspace,
65
+ overlay_store=store,
66
+ overlay_ref=ref,
67
+ overlay_source_kind="path",
68
+ overlay_source_value="myteam/dark-theme",
69
+ overlay_signer=None,
70
+ )
71
+
72
+ assert (workspace / "settings.toml").read_text() == '[ui]\ntheme = "dark"\n'
73
+ ```
74
+
75
+ ### 4. Deactivate
76
+
77
+ ```python
78
+ deactivate_overlay(workspace_root=workspace, overlay_ref=ref)
79
+ assert not (workspace / "settings.toml").exists()
80
+ ```
81
+
82
+ ## Multi-machine distribution
83
+
84
+ Overlays use identity-mapped refspecs for transport between stores:
85
+
86
+ ```python
87
+ from gr2.overlay.refs import push_overlay_ref, fetch_overlay_ref
88
+
89
+ # Machine A: push to a shared remote
90
+ push_overlay_ref(local_store, remote_store, overlay_ref)
91
+
92
+ # Machine B: fetch and activate
93
+ fetch_overlay_ref(peer_store, remote_store, overlay_ref)
94
+ activate_overlay(
95
+ workspace_root=peer_workspace,
96
+ overlay_store=peer_store,
97
+ overlay_ref=overlay_ref,
98
+ overlay_source_kind="path",
99
+ overlay_source_value="myteam/dark-theme",
100
+ overlay_signer=None,
101
+ )
102
+ ```
103
+
104
+ ## Curated merge drivers
105
+
106
+ Three drivers handle file composition when overlays interact with
107
+ existing workspace content:
108
+
109
+ | Driver | Behavior | File types |
110
+ |--------|----------|------------|
111
+ | `overlay-deep` | Recursive dict merge; overlay wins conflicts | `.toml`, `.yml`, `.json` |
112
+ | `overlay-prepend` | Concatenates overlay content before base | Any text file |
113
+ | `overlay-union` | Deduplicated line set union | Line-oriented files |
114
+
115
+ Drivers are declared in `.gitattributes`:
116
+
117
+ ```
118
+ *.toml merge=overlay-deep
119
+ *.yml merge=overlay-deep
120
+ *.json merge=overlay-deep
121
+ COMPOSE.md merge=overlay-prepend
122
+ ```
123
+
124
+ ## Trust model
125
+
126
+ Activation is gated by a workspace-local allowlist at
127
+ `.grip/trust.toml`. If no trust config exists, the workspace operates
128
+ in **open mode** (all overlays are accepted).
129
+
130
+ ```toml
131
+ [[sources]]
132
+ kind = "path"
133
+ pattern = "myteam/*"
134
+ trust_class = "local"
135
+
136
+ [[sources]]
137
+ kind = "path"
138
+ pattern = "vendor/*"
139
+ trust_class = "team"
140
+
141
+ [[sources]]
142
+ kind = "signed"
143
+ signer = "release-bot@myorg.com"
144
+ trust_class = "team"
145
+ ```
146
+
147
+ Trust classes:
148
+ - **local**: overlays from your own team or workspace
149
+ - **team**: overlays from verified external sources
150
+
151
+ Untrusted overlays are blocked before any files are written.
152
+ Path traversal patterns (containing `..`) are always rejected.
153
+
154
+ `.gitattributes` is treated as metadata, not authority: it declares
155
+ which driver to use but does not bypass the trust allowlist.
156
+
157
+ ## Introspection
158
+
159
+ Five query functions provide visibility into overlay state. Each
160
+ supports both human-readable and machine-readable (`--json`) output:
161
+
162
+ | Function | Purpose |
163
+ |----------|---------|
164
+ | `overlay_stack` | Active and available overlays with author metadata |
165
+ | `overlay_status` | Active, available, and applied overlay sets |
166
+ | `overlay_trace` | Per-file line-region attribution to overlay refs |
167
+ | `overlay_why` | Winning merge rule and reason for a file |
168
+ | `overlay_impact` | Files touched by an overlay (reads git objects directly) |
169
+
170
+ ## Performance gates
171
+
172
+ The perf harness (`gr2/overlay/perf.py`) measures overlay operations
173
+ against git baselines:
174
+
175
+ | Gate | Measures | Threshold |
176
+ |------|----------|-----------|
177
+ | `activate_vs_git_checkout_single_file` | Activate latency vs `git checkout` | 2.0x |
178
+ | `status_vs_git_status` | Overlay status vs `git status` | 2.0x |
179
+ | `diff_vs_git_diff` | Overlay diff vs `git diff` | 2.0x |
180
+
181
+ Gates use median-based sampling to reduce single-run noise.
182
+
183
+ ## WorkspaceSpec
184
+
185
+ Overlays are declared in `.grip/overlays.toml`:
186
+
187
+ ```toml
188
+ [[overlays]]
189
+ name = "dark-theme"
190
+ path = "refs/overlays/myteam/dark-theme"
191
+ applies_to = ["*.toml", "*.yml"]
192
+ priority = 10
193
+
194
+ [[overlays]]
195
+ name = "shared-base"
196
+ path = "refs/overlays/team/shared-base"
197
+ applies_to = ["*.toml"]
198
+ priority = 0
199
+ ```
200
+
201
+ Higher priority overlays take precedence during composition.
202
+
203
+ ## Object encoding
204
+
205
+ Each overlay is stored as an annotated tag pointing at a structured
206
+ tree with four entries:
207
+
208
+ ```
209
+ <tag>
210
+ └── <tree>
211
+ ├── metadata_blob # TOML metadata (author, tier, trust, timestamp)
212
+ ├── staged_index_tree # Files from the staging area
213
+ ├── untracked_blobs # Untracked file content
214
+ └── working_tree_tree # Complete working tree snapshot
215
+ ```
216
+
217
+ The Tier A filter captures only config files: `.toml`, `.yml`, `.json`
218
+ by extension, plus `COMPOSE.md` by exact filename.
219
+
220
+ ## M1 acceptance criteria
221
+
222
+ 1. Capture Tier A overlay from source directory into bare git store
223
+ 2. Push overlay ref to remote store via identity-mapped refspec
224
+ 3. Fetch overlay ref on a separate store (simulating a different machine)
225
+ 4. Activate overlay: eagerly materialize all files into workspace
226
+ 5. Verify byte-for-byte content fidelity across all Tier A file types
227
+ 6. Deactivate: remove all overlay files, clean empty parent directories
228
+ 7. Verify workspace returns to pre-overlay state
229
+ 8. Trust gating: block untrusted overlays before any file writes
230
+ 9. Open mode: no trust config permits all overlays
231
+ 10. Idempotent: activate/deactivate cycles produce identical state
232
+
233
+ All criteria are validated by the acceptance harness at
234
+ `tests/test_overlay_acceptance.py`.
235
+
236
+ ## Module reference
237
+
238
+ | Module | Purpose |
239
+ |--------|---------|
240
+ | `types.py` | Data types: `OverlayRef`, `OverlayMeta`, `OverlayTier`, `TrustLevel` |
241
+ | `objects.py` | Capture and apply overlay objects (git plumbing) |
242
+ | `refs.py` | Push and fetch overlay refs between stores |
243
+ | `drivers.py` | Curated merge drivers (deep, prepend, union) |
244
+ | `trust.py` | Workspace trust model and allowlist |
245
+ | `activate.py` | Activate and deactivate overlays |
246
+ | `introspection.py` | Query functions (stack, status, trace, why, impact) |
247
+ | `workspace_spec.py` | `[[overlays]]` TOML schema |
248
+ | `perf.py` | Performance gates measurement harness |
249
+ | `cli.py` | Typer CLI stubs for `gr overlay` subcommands |
250
+
251
+ ## Development
252
+
253
+ ```bash
254
+ pip install -e ".[dev]"
255
+ pytest
256
+ ruff check gr2/overlay/ tests/
257
+ ruff format --check gr2/overlay/ tests/
258
+ ```
gitgrip-1.5.0/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.5.0
@@ -0,0 +1,58 @@
1
+ """In-tree PEP 517 build backend: single-source the distribution version from
2
+ the repo-root ``Cargo.toml`` so a published wheel's version says which grip it
3
+ belongs to (never a hand-maintained 0.1.0 drifting from the Rust crate).
4
+
5
+ It wraps setuptools.build_meta: before every build hook it (re)writes a
6
+ ``VERSION`` file next to pyproject.toml from ``../Cargo.toml``'s
7
+ ``[package] version``. ``[tool.setuptools.dynamic] version = {file = "VERSION"}``
8
+ then reads it. Cargo.toml lives one level above the packaging root (gr2/), so it
9
+ is present for a direct wheel build and for the sdist build; a wheel built FROM
10
+ an sdist has no Cargo.toml (it is outside the packaging root), and there VERSION
11
+ travels inside the sdist (MANIFEST.in) and is left as-is.
12
+
13
+ requires-python is >=3.11, so tomllib is always stdlib — no build dependency.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import pathlib
18
+
19
+ from setuptools import build_meta as _bm
20
+
21
+ from version_from_cargo import sync_version as _sync
22
+
23
+ # Re-export the hooks we do not override so the frontend finds a complete backend.
24
+ get_requires_for_build_wheel = _bm.get_requires_for_build_wheel
25
+ get_requires_for_build_sdist = _bm.get_requires_for_build_sdist
26
+ get_requires_for_build_editable = _bm.get_requires_for_build_editable
27
+
28
+
29
+ def _sync_version() -> None:
30
+ """Write VERSION from ../Cargo.toml (via the setuptools-free helper, so the
31
+ version logic is testable in a plain venv). PEP 517 runs the backend with
32
+ cwd = the packaging root."""
33
+ _sync(pathlib.Path.cwd())
34
+
35
+
36
+ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
37
+ _sync_version()
38
+ return _bm.build_wheel(wheel_directory, config_settings, metadata_directory)
39
+
40
+
41
+ def build_sdist(sdist_directory, config_settings=None):
42
+ _sync_version()
43
+ return _bm.build_sdist(sdist_directory, config_settings)
44
+
45
+
46
+ def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
47
+ _sync_version()
48
+ return _bm.prepare_metadata_for_build_wheel(metadata_directory, config_settings)
49
+
50
+
51
+ def build_editable(wheel_directory, config_settings=None, metadata_directory=None):
52
+ _sync_version()
53
+ return _bm.build_editable(wheel_directory, config_settings, metadata_directory)
54
+
55
+
56
+ def prepare_metadata_for_build_editable(metadata_directory, config_settings=None):
57
+ _sync_version()
58
+ return _bm.prepare_metadata_for_build_editable(metadata_directory, config_settings)
@@ -0,0 +1,43 @@
1
+ """Pure version-single-sourcing helper — no setuptools import, so it is testable
2
+ in a plain runtime venv. The build backend (backend.py) delegates to it.
3
+
4
+ Writes a VERSION file from the repo-root ``Cargo.toml``'s ``[package] version``,
5
+ but ONLY when that Cargo.toml is grip's own crate (``[package] name`` ==
6
+ ``gitgrip``). Any other ``../Cargo.toml`` is ignored — an sdist unpacked one
7
+ level below an unrelated Rust project must not inherit that project's version
8
+ (measured: a foreign Cargo at 7.7.7 minted gitgrip-7.7.7 while the sdist's own
9
+ VERSION said 1.4.0). When grip's Cargo is not reachable (a wheel built FROM an
10
+ unpacked sdist), the VERSION that rode inside the sdist is used. Never invents a
11
+ version, and never trusts a foreign crate's.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import pathlib
16
+ import tomllib
17
+
18
+ _CRATE_NAME = "gitgrip"
19
+
20
+
21
+ def _grip_cargo_version(cargo: pathlib.Path) -> str | None:
22
+ """The [package] version of ``cargo`` iff it is grip's own crate, else None."""
23
+ if not cargo.is_file():
24
+ return None
25
+ pkg = tomllib.loads(cargo.read_text(encoding="utf-8")).get("package", {})
26
+ if pkg.get("name") != _CRATE_NAME:
27
+ return None # a foreign Cargo.toml — do not trust its version
28
+ return pkg.get("version")
29
+
30
+
31
+ def sync_version(root: pathlib.Path) -> str:
32
+ root = pathlib.Path(root)
33
+ version_file = root / "VERSION"
34
+ version = _grip_cargo_version(root.parent / "Cargo.toml")
35
+ if version is not None:
36
+ version_file.write_text(version + "\n", encoding="utf-8")
37
+ return version
38
+ if version_file.is_file() and version_file.read_text(encoding="utf-8").strip():
39
+ return version_file.read_text(encoding="utf-8").strip()
40
+ raise RuntimeError(
41
+ f"cannot single-source version at {root}: no grip Cargo.toml "
42
+ f"([package] name = {_CRATE_NAME!r}) above it and no populated VERSION file"
43
+ )
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitgrip
3
+ Version: 1.5.0
4
+ Summary: gr2 overlay substrate: config-overlay capture, composition, and materialization
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: typer>=0.9
7
+ Requires-Dist: tomli_w>=1.0
8
+ Requires-Dist: pyyaml>=6.0
9
+ Requires-Dist: toml>=0.10
10
+ Requires-Dist: jsonschema>=4.18
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=8.0; extra == "dev"
13
+ Requires-Dist: ruff>=0.4; extra == "dev"
@@ -0,0 +1,199 @@
1
+ MANIFEST.in
2
+ README.md
3
+ VERSION
4
+ pyproject.toml
5
+ _build/backend.py
6
+ _build/version_from_cargo.py
7
+ _build/__pycache__/backend.cpython-311.pyc
8
+ _build/__pycache__/version_from_cargo.cpython-311.pyc
9
+ gitgrip.egg-info/PKG-INFO
10
+ gitgrip.egg-info/SOURCES.txt
11
+ gitgrip.egg-info/dependency_links.txt
12
+ gitgrip.egg-info/entry_points.txt
13
+ gitgrip.egg-info/requires.txt
14
+ gitgrip.egg-info/top_level.txt
15
+ gr2/__init__.py
16
+ gr2/overlay/__init__.py
17
+ gr2/overlay/activate.py
18
+ gr2/overlay/agent_manifest.py
19
+ gr2/overlay/cli.py
20
+ gr2/overlay/cross_repo.py
21
+ gr2/overlay/drivers.py
22
+ gr2/overlay/introspection.py
23
+ gr2/overlay/language_drivers.py
24
+ gr2/overlay/objects.py
25
+ gr2/overlay/perf.py
26
+ gr2/overlay/refs.py
27
+ gr2/overlay/trust.py
28
+ gr2/overlay/types.py
29
+ gr2/overlay/units.py
30
+ gr2/overlay/workspace_spec.py
31
+ gr2/schemas/gr2-materialization-plan-v1.schema.json
32
+ gr2_overlay/__init__.py
33
+ prototypes/__init__.py
34
+ prototypes/cache_materialization_probe.py
35
+ prototypes/concurrent_event_stress.py
36
+ prototypes/concurrent_lease_stress.py
37
+ prototypes/concurrent_workspace_cap_stress.py
38
+ prototypes/contribution_protocol.py
39
+ prototypes/cross_mode_lane_stress.py
40
+ prototypes/jsonl_store.py
41
+ prototypes/lane_workspace_prototype.py
42
+ prototypes/layout_model_probe.py
43
+ prototypes/propagation_daemon.py
44
+ prototypes/propagation_state_machine.py
45
+ prototypes/python_exec_playground.py
46
+ prototypes/python_hook_runtime_playground.py
47
+ prototypes/python_migration_playground.py
48
+ prototypes/python_review_checkout_playground.py
49
+ prototypes/python_spec_apply_playground.py
50
+ prototypes/real_git_lane_materialization.py
51
+ prototypes/real_git_playground.py
52
+ prototypes/recall_lane_history.py
53
+ prototypes/repo_maintenance_prototype.py
54
+ prototypes/repo_transport_probe.py
55
+ python_cli/__init__.py
56
+ python_cli/__main__.py
57
+ python_cli/add.py
58
+ python_cli/app.py
59
+ python_cli/branch.py
60
+ python_cli/channel_bridge.py
61
+ python_cli/clone_exec.py
62
+ python_cli/commit.py
63
+ python_cli/config.py
64
+ python_cli/env_exec.py
65
+ python_cli/events.py
66
+ python_cli/execops.py
67
+ python_cli/failures.py
68
+ python_cli/file_exec.py
69
+ python_cli/gitops.py
70
+ python_cli/grip.py
71
+ python_cli/grip_cli.py
72
+ python_cli/hooks.py
73
+ python_cli/launch_exec.py
74
+ python_cli/merge_verification.py
75
+ python_cli/migration.py
76
+ python_cli/open_gr_review.py
77
+ python_cli/platform.py
78
+ python_cli/pr.py
79
+ python_cli/project_review.py
80
+ python_cli/prune.py
81
+ python_cli/push.py
82
+ python_cli/review.py
83
+ python_cli/review_ephemeral.py
84
+ python_cli/review_run.py
85
+ python_cli/spec_apply.py
86
+ python_cli/staging_cleanup.py
87
+ python_cli/syncops.py
88
+ python_cli/target.py
89
+ python_cli/workspace_snapshot.py
90
+ tests/test_add.py
91
+ tests/test_agent_manifest_overlay_source.py
92
+ tests/test_app_event_outcomes.py
93
+ tests/test_apply_convergence.py
94
+ tests/test_branch.py
95
+ tests/test_channel_bridge.py
96
+ tests/test_clone_materialization.py
97
+ tests/test_commit.py
98
+ tests/test_config_base_path_guard.py
99
+ tests/test_config_overlay.py
100
+ tests/test_contribution_protocol.py
101
+ tests/test_ensure_lane_checkout_reference_clone.py
102
+ tests/test_env_materialization.py
103
+ tests/test_event_log_integrity.py
104
+ tests/test_event_outcome_policy.py
105
+ tests/test_events.py
106
+ tests/test_events_torn_line.py
107
+ tests/test_execops.py
108
+ tests/test_failure_event_outcome.py
109
+ tests/test_gr2_packaging.py
110
+ tests/test_gr2_review_receipt.py
111
+ tests/test_grip_cli.py
112
+ tests/test_grip_hardening.py
113
+ tests/test_grip_object_model.py
114
+ tests/test_grip_snapshot.py
115
+ tests/test_hook_events.py
116
+ tests/test_hook_hardening.py
117
+ tests/test_jsonl_store.py
118
+ tests/test_lane_create_fork_base_cli.py
119
+ tests/test_lane_lease_show_json.py
120
+ tests/test_lane_lifecycle_safety.py
121
+ tests/test_lane_toml_serialization.py
122
+ tests/test_launch_primitive.py
123
+ tests/test_m2_overlay_hindsight.py
124
+ tests/test_m2_overlay_mem0.py
125
+ tests/test_m2_overlay_zep.py
126
+ tests/test_materialization_plan_contract.py
127
+ tests/test_merge_evidence.py
128
+ tests/test_merge_parent_verification.py
129
+ tests/test_migration.py
130
+ tests/test_migration_overlay_compatibility.py
131
+ tests/test_no_bare_python_cli_imports.py
132
+ tests/test_null_current_lane_refusal.py
133
+ tests/test_open_gr_enter.py
134
+ tests/test_open_project_refusal_reason_cli.py
135
+ tests/test_overlay_acceptance.py
136
+ tests/test_overlay_activate.py
137
+ tests/test_overlay_cli.py
138
+ tests/test_overlay_cli_wiring.py
139
+ tests/test_overlay_composition_merge.py
140
+ tests/test_overlay_cross_repo_atomic_apply.py
141
+ tests/test_overlay_cross_repo_perf_gate.py
142
+ tests/test_overlay_cross_repo_rollback.py
143
+ tests/test_overlay_driver_registry.py
144
+ tests/test_overlay_introspection.py
145
+ tests/test_overlay_multi_stack.py
146
+ tests/test_overlay_object_encoding.py
147
+ tests/test_overlay_perf_gates.py
148
+ tests/test_overlay_python_driver.py
149
+ tests/test_overlay_tier_b_encoding.py
150
+ tests/test_overlay_tier_b_perf_gates.py
151
+ tests/test_overlay_tier_b_repo_state.py
152
+ tests/test_overlay_tier_b_staging_discipline.py
153
+ tests/test_overlay_trust_model.py
154
+ tests/test_overlay_workspace_spec.py
155
+ tests/test_pr_events.py
156
+ tests/test_pr_merge_method.py
157
+ tests/test_pr_merge_partial_failure.py
158
+ tests/test_project_file_materialization.py
159
+ tests/test_project_review_range_reconstruction.py
160
+ tests/test_project_review_three_repo.py
161
+ tests/test_propagation_contribution.py
162
+ tests/test_propagation_daemon.py
163
+ tests/test_propagation_state_machine.py
164
+ tests/test_prune.py
165
+ tests/test_push.py
166
+ tests/test_repo_status_linked_worktree.py
167
+ tests/test_repo_status_schema_version.py
168
+ tests/test_repo_status_symlinked_git_dir.py
169
+ tests/test_review_bind_fork_base.py
170
+ tests/test_review_bind_from_range.py
171
+ tests/test_review_bind_verify.py
172
+ tests/test_review_cli.py
173
+ tests/test_review_close_gr.py
174
+ tests/test_review_create_project_cli.py
175
+ tests/test_review_ephemeral.py
176
+ tests/test_review_open_lane.py
177
+ tests/test_review_run.py
178
+ tests/test_review_verify_inside.py
179
+ tests/test_rmtree_or_refuse.py
180
+ tests/test_snapshot_id_prefix_resolution.py
181
+ tests/test_spec_apply_event_outcomes.py
182
+ tests/test_sprint21_sync_platform.py
183
+ tests/test_staging_cleanup.py
184
+ tests/test_sync_event_outcomes.py
185
+ tests/test_sync_fetch.py
186
+ tests/test_target.py
187
+ tests/test_tmux_launch_runtime.py
188
+ tests/test_unit_abort.py
189
+ tests/test_unit_apply.py
190
+ tests/test_unit_apply_dry_run.py
191
+ tests/test_unit_manifest_schema.py
192
+ tests/test_unit_propose.py
193
+ tests/test_unit_topological_apply.py
194
+ tests/test_version_single_sourced.py
195
+ tests/test_workspace_convert_clone.py
196
+ tests/test_workspace_edit_lease_cap.py
197
+ tests/test_workspace_identity_boundary.py
198
+ tests/test_workspace_init_from_topology.py
199
+ tests/test_workspace_snapshot.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ gr2 = gr2.python_cli.app:main
@@ -0,0 +1,9 @@
1
+ typer>=0.9
2
+ tomli_w>=1.0
3
+ pyyaml>=6.0
4
+ toml>=0.10
5
+ jsonschema>=4.18
6
+
7
+ [dev]
8
+ pytest>=8.0
9
+ ruff>=0.4
@@ -0,0 +1,2 @@
1
+ gr2
2
+ gr2_overlay
File without changes
@@ -0,0 +1,6 @@
1
+ """gr2 overlay substrate: config-overlay capture, composition, and materialization.
2
+
3
+ M1 scope: Tier A only (config files), eager materialization, trust-gated.
4
+ """
5
+
6
+ __version__ = "0.1.0"