gitvow 0.34.1__tar.gz → 0.34.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitvow-0.34.1/src/gitvow.egg-info → gitvow-0.34.2}/PKG-INFO +1 -1
- {gitvow-0.34.1 → gitvow-0.34.2}/pyproject.toml +1 -1
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/hooks/__init__.py +15 -8
- {gitvow-0.34.1 → gitvow-0.34.2/src/gitvow.egg-info}/PKG-INFO +1 -1
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_hooks_disabled.py +20 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/LICENSE +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/README.md +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/setup.cfg +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/__init__.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/__main__.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/adapters.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/carry.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/claims.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/cli.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/collect.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/decisions.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/default_policy.json +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/digest.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/export.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/install.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/intent.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/notes.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/outcomes.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/pack.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/paths.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/policy.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/pricing.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/proposals.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/providers.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/reach.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/recall.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/redact.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/report.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/rules.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/safewrite.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/scan.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/selftest.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/serve.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/snapshots.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/state.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/status.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/sync.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/targets.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow/transcript.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow.egg-info/SOURCES.txt +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow.egg-info/dependency_links.txt +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow.egg-info/entry_points.txt +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow.egg-info/requires.txt +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/src/gitvow.egg-info/top_level.txt +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_adapters.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_answered_confirm_commit.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_carry.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_claims.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_collect.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_command_position.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_commit_window.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_cost.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_decisions.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_defects_0_32_1.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_digest.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_duplicate_hooks.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_e2e_globalopt.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_export.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_external_adapter.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_git_rules.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_hardening.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_hooks.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_install_cli.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_intent.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_native_question.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_opencode.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_outcomes.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_pack.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_packaging.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_policy.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_policy_refresh.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_proposals.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_providers.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_reach.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_recall.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_redact.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_report.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_rules.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_scan.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_serve.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_snapshots.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_status.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_status_environment.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_symlinked_paths.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_sync.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_sync_http.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_targets.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_tiers.py +0 -0
- {gitvow-0.34.1 → gitvow-0.34.2}/tests/test_transcript_formats.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitvow
|
|
3
|
-
Version: 0.34.
|
|
3
|
+
Version: 0.34.2
|
|
4
4
|
Summary: Provenance and policy gate for AI-agent coding sessions: session trailers on commits, redacted session notes in git, a tool-call gate, and a local ledger. No runtime dependencies.
|
|
5
5
|
Author-email: Nikhil Bora <nikhil@wirevow.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gitvow"
|
|
7
|
-
version = "0.34.
|
|
7
|
+
version = "0.34.2"
|
|
8
8
|
description = "Provenance and policy gate for AI-agent coding sessions: session trailers on commits, redacted session notes in git, a tool-call gate, and a local ledger. No runtime dependencies."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
@@ -469,6 +469,21 @@ def post_tool_use(h: dict[str, Any], home: str | None = None) -> tuple[int, str]
|
|
|
469
469
|
cwd = target_cwd(tool, inp, session_cwd)
|
|
470
470
|
if _duplicate(h, cwd, "post"):
|
|
471
471
|
return 0, ""
|
|
472
|
+
code, msg = _post_tool_use(h, home, tool, inp, cwd)
|
|
473
|
+
if tool == "Bash" and PUSH_RE.search(inp.get("command", "")) and not os.environ.get("GITVOW_PUSHING_NOTES"):
|
|
474
|
+
# The notes travel after the branch, never alongside it: the pre-push hook stepped aside for this push
|
|
475
|
+
# (or never ran, as under Gemini). Done last, after any note for a `commit && push` chain was attached,
|
|
476
|
+
# so the note travels with the push it belongs to.
|
|
477
|
+
st = load_state(cwd)
|
|
478
|
+
if "pending_push" in st:
|
|
479
|
+
st.pop("pending_push", None)
|
|
480
|
+
save_state(cwd, st)
|
|
481
|
+
_push_notes_after(cwd, inp.get("command", ""))
|
|
482
|
+
return code, msg
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def _post_tool_use(h: dict[str, Any], home: str | None, tool: str, inp: dict[str, Any], cwd: str) -> tuple[int, str]:
|
|
486
|
+
session_cwd = h.get("cwd") or os.getcwd()
|
|
472
487
|
if tool in EDIT_TOOLS:
|
|
473
488
|
fp = str(inp.get("file_path") or inp.get("notebook_path") or "")
|
|
474
489
|
if fp:
|
|
@@ -489,14 +504,6 @@ def post_tool_use(h: dict[str, Any], home: str | None = None) -> tuple[int, str]
|
|
|
489
504
|
return 0, ""
|
|
490
505
|
if tool == "Bash" and not COMMIT_RE.search(inp.get("command", "")):
|
|
491
506
|
_record_prompt_approval(cwd, inp, home)
|
|
492
|
-
if PUSH_RE.search(inp.get("command", "")) and not os.environ.get("GITVOW_PUSHING_NOTES"):
|
|
493
|
-
# The notes travel after the branch, never alongside it: the pre-push hook stepped aside for this
|
|
494
|
-
# push (or never ran, as under Gemini), so carry them now, sequentially.
|
|
495
|
-
st = load_state(cwd)
|
|
496
|
-
if "pending_push" in st:
|
|
497
|
-
st.pop("pending_push", None)
|
|
498
|
-
save_state(cwd, st)
|
|
499
|
-
_push_notes_after(cwd, inp.get("command", ""))
|
|
500
507
|
return 0, ""
|
|
501
508
|
if tool != "Bash":
|
|
502
509
|
return 0, ""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitvow
|
|
3
|
-
Version: 0.34.
|
|
3
|
+
Version: 0.34.2
|
|
4
4
|
Summary: Provenance and policy gate for AI-agent coding sessions: session trailers on commits, redacted session notes in git, a tool-call gate, and a local ledger. No runtime dependencies.
|
|
5
5
|
Author-email: Nikhil Bora <nikhil@wirevow.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -157,3 +157,23 @@ def test_the_pre_push_hook_steps_aside_for_an_agents_push(repo, home, payload, t
|
|
|
157
157
|
git(repo, "notes", "--ref=gitvow/s1", "add", "-f", "-m", 'gitvow-session\n{"y": 2}', "HEAD")
|
|
158
158
|
subprocess.run(["git", "push", "-q", "origin", "HEAD:refs/heads/feature2"], cwd=repo, check=True)
|
|
159
159
|
assert git(bare, "rev-parse", "refs/notes/gitvow/s1") == git(repo, "rev-parse", "refs/notes/gitvow/s1")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_a_commit_and_push_chain_sends_the_note_with_the_push(repo, home, payload, transcript, tmp_path):
|
|
163
|
+
"""`git commit … && git push` takes the commit path; the notes must still follow, after the note is attached."""
|
|
164
|
+
bare = tmp_path / "remote.git"
|
|
165
|
+
subprocess.run(["git", "init", "-q", "--bare", str(bare)], check=True)
|
|
166
|
+
git(repo, "remote", "add", "origin", str(bare))
|
|
167
|
+
_write_git_hook(str(repo / ".gitvow" / "git-hooks"))
|
|
168
|
+
git(repo, "config", "core.hooksPath", ".gitvow/git-hooks")
|
|
169
|
+
session_start(payload("SessionStart"), str(home))
|
|
170
|
+
cmd = "git commit -am x && git push origin HEAD:refs/heads/feature" # not protected: no question
|
|
171
|
+
assert pre_tool_use(payload("PreToolUse", "Bash", {"command": cmd}, transcript), str(home))[0] == 0
|
|
172
|
+
(repo / "a.txt").write_text("chain\n")
|
|
173
|
+
git(repo, "commit", "-qam", "chain")
|
|
174
|
+
subprocess.run(["git", "push", "-q", "origin", "HEAD:refs/heads/feature"], cwd=repo, check=True)
|
|
175
|
+
assert git(bare, "for-each-ref", "refs/notes/") == "" # the hook stepped aside for the agent's push
|
|
176
|
+
code, msg = post_tool_use(payload("PostToolUse", "Bash", {"command": cmd}, transcript), str(home))
|
|
177
|
+
assert code == 0 and "session note attached" in msg
|
|
178
|
+
local = git(repo, "rev-parse", "refs/notes/gitvow/sess-1")
|
|
179
|
+
assert git(bare, "rev-parse", "refs/notes/gitvow/sess-1") == local # the note just written is on the remote
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|