ai-push-hooks 0.2.0 → 0.2.1
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.
- package/CHANGELOG.md +24 -2
- package/README.md +27 -9
- package/SECURITY.md +1 -1
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/ai_push_hooks/executors/exec.py +9 -1
- package/src/ai_push_hooks/executors/llm.py +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,28 @@ All notable changes to this project are documented here. The format is based on
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## [0.2.1] - 2026-09-08
|
|
8
|
+
|
|
9
|
+
This is a beta patch release. Python and npm both use `0.2.1`, the canonical
|
|
10
|
+
Git tag is `v0.2.1`, npm uses the `beta` dist-tag, and GitHub marks the release
|
|
11
|
+
as a prerelease.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Restored OpenCode's built-in plugins, including built-in authentication such as
|
|
16
|
+
Codex OAuth, during isolated runs. `--pure` still excludes external plugins,
|
|
17
|
+
and project/global configuration and plugins remain isolated.
|
|
18
|
+
- Restored forwarding of recognized provider environment variables, including
|
|
19
|
+
`OPENAI_API_KEY`, so OpenCode itself selects the authentication path.
|
|
20
|
+
- Prevented hook-launched Beads alignment updates from inheriting schema and
|
|
21
|
+
remote-migration safety overrides.
|
|
22
|
+
- Made post-publication PyPI verification tolerate bounded 404/partial metadata
|
|
23
|
+
propagation while retaining fail-closed artifact hash and authentication checks.
|
|
24
|
+
|
|
25
|
+
### Documentation
|
|
26
|
+
|
|
27
|
+
- Documented the native `bd` maintenance, backup, rehearsal, and remote
|
|
28
|
+
publication boundaries; Beads-Rust (`br`) is not supported.
|
|
8
29
|
|
|
9
30
|
## [0.2.0] - 2026-09-06
|
|
10
31
|
|
|
@@ -58,6 +79,7 @@ the exact `0.2.0` version rather than a PyPI beta channel.
|
|
|
58
79
|
- Preserved Git porcelain paths and protected pre-existing dirty allowlisted files during apply steps.
|
|
59
80
|
- Clarified module-local artifact references and standardized the repository hook integration.
|
|
60
81
|
|
|
61
|
-
[Unreleased]: https://github.com/shanebishop1/ai-push-hooks/compare/v0.2.
|
|
82
|
+
[Unreleased]: https://github.com/shanebishop1/ai-push-hooks/compare/v0.2.1...HEAD
|
|
83
|
+
[0.2.1]: https://github.com/shanebishop1/ai-push-hooks/compare/v0.2.0...v0.2.1
|
|
62
84
|
[0.2.0]: https://github.com/shanebishop1/ai-push-hooks/compare/v0.1.19...v0.2.0
|
|
63
85
|
[0.1.19]: https://github.com/shanebishop1/ai-push-hooks/compare/v0.1.18...v0.1.19
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Use it to keep docs aligned with code, check branch/task consistency, or prepare
|
|
|
12
12
|
- [Python 3.10–3.13](https://www.python.org/downloads/). Python is required even when installing the npm wrapper. The wrapper probes Python 3.14, 3.13, 3.12, 3.11, 3.10, then `python`; the 3.14 probe is not a beta support claim. Python 3.10 additionally needs the `tomli` package available to that interpreter.
|
|
13
13
|
- [OpenCode](https://opencode.ai/docs/#install) is optional for workflows that use only deterministic steps, but the `minimal-docs` starter uses `llm` and `apply`. Those steps also need a provider/model and authentication; check with `opencode auth list`.
|
|
14
14
|
- [GitHub CLI (`gh`)](https://cli.github.com/manual/installation) is optional and needed only for `gh_pr_create`.
|
|
15
|
-
- [Beads (`bd`)](https://github.com/steveyegge/beads) is optional and needed only for Beads alignment steps.
|
|
15
|
+
- [Beads (`bd`)](https://github.com/steveyegge/beads) is optional and needed only for Beads alignment steps. The integration requires the native `bd` CLI; Beads-Rust (`br`) is not a supported substitute.
|
|
16
16
|
- [Lefthook](https://lefthook.dev/installation/) and [Mise](https://mise.jdx.dev/getting-started.html) are optional hook-manager/tool-version alternatives described below.
|
|
17
17
|
|
|
18
18
|
### Install ai-push-hooks
|
|
@@ -21,7 +21,7 @@ This is the shortest path. It installs the package, writes the exact starter
|
|
|
21
21
|
configuration filename, and installs a repository-local `pre-push` delegate:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
python -m pip install ai-push-hooks==0.2.
|
|
24
|
+
python -m pip install ai-push-hooks==0.2.1
|
|
25
25
|
ai-push-hooks init --template minimal-docs
|
|
26
26
|
ai-push-hooks install
|
|
27
27
|
```
|
|
@@ -33,9 +33,9 @@ the bare remote. The first command above can instead be `uv tool install
|
|
|
33
33
|
ai-push-hooks` or `pipx install ai-push-hooks` when using an isolated
|
|
34
34
|
application environment.
|
|
35
35
|
|
|
36
|
-
These instructions describe the `0.2.
|
|
36
|
+
These instructions describe the `0.2.1` beta release. npm exposes it through
|
|
37
37
|
the `beta` dist-tag; PyPI has no separate beta channel, so Python installation
|
|
38
|
-
must select the exact `0.2.
|
|
38
|
+
must select the exact `0.2.1` version. Published `0.1.19` artifacts retain
|
|
39
39
|
historical provenance and must not be assumed to contain this release's
|
|
40
40
|
`install` command.
|
|
41
41
|
|
|
@@ -55,7 +55,7 @@ npx --no-install ai-push-hooks install
|
|
|
55
55
|
# or: pnpm add -D ai-push-hooks && pnpm exec ai-push-hooks install
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Use `ai-push-hooks@0.2.
|
|
58
|
+
Use `ai-push-hooks@0.2.1` instead of `@beta` when an exact npm version pin is
|
|
59
59
|
required.
|
|
60
60
|
|
|
61
61
|
The npm package does not contain a Python runtime. Ensure the Python
|
|
@@ -85,14 +85,14 @@ resolved. The fallback delegate fails clearly with status 127 if
|
|
|
85
85
|
Pin an approved published release in the consuming repository:
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
mise use npm:ai-push-hooks@0.2.
|
|
88
|
+
mise use npm:ai-push-hooks@0.2.1
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
This adds the following project-level tool entry to `mise.toml` and installs it:
|
|
92
92
|
|
|
93
93
|
```toml
|
|
94
94
|
[tools]
|
|
95
|
-
"npm:ai-push-hooks" = "0.2.
|
|
95
|
+
"npm:ai-push-hooks" = "0.2.1"
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
After checking in `mise.toml`, other contributors can install the pinned tool with `mise install`.
|
|
@@ -101,12 +101,30 @@ After checking in `mise.toml`, other contributors can install the pinned tool wi
|
|
|
101
101
|
|
|
102
102
|
OpenCode runs in `--pure` mode with project configuration disabled, isolated home/config/cache/state directories, sharing disabled, and an ai-push-hooks-owned custom agent configuration. Read-only steps run in an empty scratch directory, receive only hook-owned artifacts through `--file`, and have every tool denied. Apply steps run against a private temporary workspace containing only unignored regular files matching `allow_paths`; their agent permits only reads and allowlisted edits in that workspace. Casefolded, Unicode-normalized `.git` and `AGENTS.md` paths are always protected.
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
Built-in OpenCode plugins remain enabled, including built-in authentication plugins such as Codex OAuth. Normal `--pure` execution disables external plugins, while the hook's empty plugin configuration and project-config disablement prevent project and global plugins and configuration from being inherited. The existing XDG data directory is retained for OpenCode authentication/session state, and recognized provider environment variables, including `OPENAI_API_KEY`, are forwarded; OpenCode itself chooses the authentication path using its normal precedence. Custom providers defined only in global OpenCode configuration are therefore unsupported; use a built-in provider with OpenCode auth state or environment credentials.
|
|
105
105
|
|
|
106
106
|
After OpenCode session finalization, apply verifies that the Git-visible checkout, index, current-worktree control state, and critical shared `HEAD`/config/packed-refs/refs/hooks state still match their baselines. Pre-existing symlinks in monitored Git metadata fail closed before OpenCode runs, and symlinks introduced during execution fail before propagation. Apply then preflights every destination against its exact baseline type, content digest, and mode before propagating anything, performs atomic file replacement, and verifies the resulting checkout and protected Git state again. Safe existing ordinary `rwx` modes are preserved, existing special bits are stripped, new or group/world-writable modes become owner-only, and staged files carrying setuid/setgid/sticky bits are rejected before any propagation. Hook-owned runtime files default to `0600` and runtime directories to `0700`.
|
|
107
107
|
|
|
108
108
|
These controls are OpenCode permission and workspace isolation, not an operating-system sandbox. Compare-and-swap preflight minimizes lost updates but cannot make the interval between preflight and filesystem replacement atomic against an independent local process. Ignored worktree trees, Git object/LFS stores, shared reflogs, and metadata belonging only to other linked worktrees are intentionally excluded from bounded snapshots; direct changes there may not be detected. Critical shared refs/config/hooks remain monitored. Automatic rollback is avoided so pre-existing user changes are not overwritten.
|
|
109
109
|
|
|
110
|
+
### Beads maintenance boundary
|
|
111
|
+
|
|
112
|
+
The `beads_alignment` executor is for ordinary native `bd update` and `bd close`
|
|
113
|
+
operations only. It does not run migrations, synchronize embedded Dolt, or
|
|
114
|
+
publish Dolt refs. Hook-launched Beads commands also discard
|
|
115
|
+
`BD_ALLOW_REMOTE_MIGRATE`, `BD_IGNORE_SCHEMA_SKEW`, and `BD_SMART_GATE` from
|
|
116
|
+
their inherited environment so an operator maintenance override cannot leak
|
|
117
|
+
into a push hook.
|
|
118
|
+
|
|
119
|
+
Treat a Beads schema migration as separate operator maintenance. Pin and
|
|
120
|
+
verify the native `bd` version, stop Beads writers and hooks, take a cold full
|
|
121
|
+
backup of `.beads`, and rehearse against a disposable copy before opening the
|
|
122
|
+
live embedded-Dolt store. Verify the schema, semantic issue/dependency data,
|
|
123
|
+
memories, and a clean Dolt working set before and after the live cutover.
|
|
124
|
+
Remote publication, including `bd dolt push`, is a separate explicit action;
|
|
125
|
+
a successful local migration does not authorize it. Do not replace this flow
|
|
126
|
+
with Beads-Rust (`br`).
|
|
127
|
+
|
|
110
128
|
## Full-featured alternative: Lefthook
|
|
111
129
|
|
|
112
130
|
Use Lefthook when the repository needs several hook commands, shared hook
|
|
@@ -160,7 +178,7 @@ Configure modules and steps in the [configuration reference](#configuration-refe
|
|
|
160
178
|
## Troubleshooting
|
|
161
179
|
|
|
162
180
|
- **`opencode is required but not installed`:** install OpenCode and ensure `opencode` (or `opencode-cli`) is on `PATH` for the Git hook process.
|
|
163
|
-
- **Provider/model authentication fails:** run `opencode auth list`, authenticate a built-in provider, and verify `[llm].model`.
|
|
181
|
+
- **Provider/model authentication fails:** run `opencode auth list`, authenticate a built-in provider, and verify `[llm].model`. Built-in auth plugins remain available, while project/global custom-provider configuration is intentionally not loaded. Recognized provider environment variables, including `OPENAI_API_KEY`, are forwarded and OpenCode chooses authentication. See [OpenCode isolation limits](#opencode-isolation-limits).
|
|
164
182
|
- **The hook does not run:** rerun `lefthook install`, check `git config --get core.hooksPath`, and verify the pre-push path with the command above.
|
|
165
183
|
- **The push is blocked after docs changed:** this is the expected edit-review-commit flow. Review `git diff`, validate and commit the changes, then push again.
|
|
166
184
|
- **Find logs or transcripts:** inspect `.git/ai-push-hooks/logs`, `.git/ai-push-hooks/summaries`, and (when enabled) `.git/ai-push-hooks/transcripts`.
|
package/SECURITY.md
CHANGED
|
@@ -8,7 +8,7 @@ Please do not open a public issue for a suspected vulnerability. Report it priva
|
|
|
8
8
|
|
|
9
9
|
ai-push-hooks treats repository content, Git paths and metadata, configuration, model output, and concurrent local filesystem changes as potentially unsafe. Its controls constrain model-visible inputs and apply destinations, protect Git metadata and instruction files, validate filesystem state before propagation, and fail closed by default. They are designed to prevent accidental or model-directed changes outside configured boundaries, not to protect against a malicious user or process with the same operating-system permissions.
|
|
10
10
|
|
|
11
|
-
OpenCode is a separate local process and communicates with the model provider selected in `[llm].model`. Diffs, changed-file context, prompts, and step artifacts can therefore leave the machine under that provider's terms. ai-push-hooks forwards recognized provider credential environment variables
|
|
11
|
+
OpenCode is a separate local process and communicates with the model provider selected in `[llm].model`. Diffs, changed-file context, prompts, and step artifacts can therefore leave the machine under that provider's terms. ai-push-hooks retains OpenCode's existing authentication data directory and forwards recognized provider credential environment variables, including `OPENAI_API_KEY`; OpenCode itself chooses authentication using its normal precedence. Built-in authentication plugins remain available, while `--pure` excludes external plugins and the isolated project/config setup excludes project/global plugins, MCP servers, instructions, and custom-provider configuration. Do not commit secrets, and review provider retention and privacy policies before use on sensitive repositories.
|
|
12
12
|
|
|
13
13
|
Hook logs, summaries, run artifacts, and transcripts are stored locally under `.git/ai-push-hooks/` with private runtime permissions. Transcript capture defaults to **on** at `.git/ai-push-hooks/transcripts`; set `logging.capture_llm_transcript = false` to disable it. OpenCode session deletion defaults to on, but provider-side retention is controlled by the provider.
|
|
14
14
|
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ai-push-hooks"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Run structured AI-assisted checks and allowlisted maintenance before git push"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -78,6 +78,13 @@ BEADS_ENV_NAMES = frozenset(
|
|
|
78
78
|
}
|
|
79
79
|
)
|
|
80
80
|
BEADS_ENV_PREFIXES = ("AWS_", "BD_", "BEADS_", "DOLT_")
|
|
81
|
+
BEADS_MIGRATION_OVERRIDE_ENV_NAMES = frozenset(
|
|
82
|
+
{
|
|
83
|
+
"BD_ALLOW_REMOTE_MIGRATE",
|
|
84
|
+
"BD_IGNORE_SCHEMA_SKEW",
|
|
85
|
+
"BD_SMART_GATE",
|
|
86
|
+
}
|
|
87
|
+
)
|
|
81
88
|
GITHUB_REPOSITORY_COMPONENT = re.compile(r"[A-Za-z0-9_.-]+\Z")
|
|
82
89
|
GIT_DIFF_CHUNK_BYTES = 64 * 1024
|
|
83
90
|
GIT_ERROR_BYTES = 64 * 1024
|
|
@@ -950,7 +957,8 @@ def beads_alignment_env() -> dict[str, str]:
|
|
|
950
957
|
return {
|
|
951
958
|
name: value
|
|
952
959
|
for name, value in os.environ.items()
|
|
953
|
-
if name in
|
|
960
|
+
if name not in BEADS_MIGRATION_OVERRIDE_ENV_NAMES
|
|
961
|
+
and (name in BEADS_ENV_NAMES or name.startswith(BEADS_ENV_PREFIXES))
|
|
954
962
|
}
|
|
955
963
|
|
|
956
964
|
|
|
@@ -100,7 +100,6 @@ def opencode_isolation_env(
|
|
|
100
100
|
"OPENCODE_DISABLE_CLAUDE_CODE": "true",
|
|
101
101
|
"OPENCODE_DISABLE_CLAUDE_CODE_PROMPT": "true",
|
|
102
102
|
"OPENCODE_DISABLE_CLAUDE_CODE_SKILLS": "true",
|
|
103
|
-
"OPENCODE_DISABLE_DEFAULT_PLUGINS": "true",
|
|
104
103
|
"OPENCODE_DISABLE_LSP_DOWNLOAD": "true",
|
|
105
104
|
"OPENCODE_DISABLE_SHARE": "true",
|
|
106
105
|
"OPENCODE_DISABLE_AUTOUPDATE": "true",
|