worktree-env 0.3.0__tar.gz → 0.3.1__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.
- {worktree_env-0.3.0 → worktree_env-0.3.1}/CHANGELOG.md +5 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/PKG-INFO +7 -7
- {worktree_env-0.3.0 → worktree_env-0.3.1}/README.md +6 -6
- {worktree_env-0.3.0 → worktree_env-0.3.1}/README.zh-CN.md +2 -2
- {worktree_env-0.3.0 → worktree_env-0.3.1}/pyproject.toml +1 -1
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/__init__.py +1 -1
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/config.py +3 -3
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/reconciler.py +4 -1
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/test_config.py +1 -1
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/test_reconciler.py +24 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/uv.lock +1 -1
- {worktree_env-0.3.0 → worktree_env-0.3.1}/.github/workflows/publish.yml +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/.github/workflows/tests.yml +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/.gitignore +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/CONTRIBUTING.md +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/LICENSE +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/SECURITY.md +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/examples/fullstack.yaml +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/__main__.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/cli.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/hooks.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/paths.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/profiles.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/projector.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/registry.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/src/worktree_env/utils.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/conftest.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/test_cli.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/test_hooks.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/test_profiles.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/test_projector.py +0 -0
- {worktree_env-0.3.0 → worktree_env-0.3.1}/tests/test_registry.py +0 -0
|
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.3.1] - 2026-08-21
|
|
8
|
+
|
|
9
|
+
- Run profile initializers from the Monitor Reconciler so worktrees created by
|
|
10
|
+
sandboxed coding agents and IDEs receive the same setup as hook-created worktrees.
|
|
11
|
+
|
|
7
12
|
## [0.3.0] - 2026-08-21
|
|
8
13
|
|
|
9
14
|
- Changed profile initializers to `command` and `args` string arrays, executed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: worktree-env
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Per-worktree ports, secrets, and local environment setup for Git
|
|
5
5
|
Project-URL: Homepage, https://github.com/archcst/worktree-env
|
|
6
6
|
Project-URL: Repository, https://github.com/archcst/worktree-env
|
|
@@ -262,8 +262,8 @@ minimal.
|
|
|
262
262
|
The Reconciler:
|
|
263
263
|
|
|
264
264
|
1. Runs `git worktree list --porcelain` to retrieve the actual list of worktrees.
|
|
265
|
-
2. Compares it with `ports.json`, then assigns ports, mounts secrets,
|
|
266
|
-
files for unregistered worktrees.
|
|
265
|
+
2. Compares it with `ports.json`, then assigns ports, mounts secrets, generates
|
|
266
|
+
files, and starts configured initializers for unregistered worktrees.
|
|
267
267
|
|
|
268
268
|
After adding a profile or changing a `main_worktree` path, run this command again:
|
|
269
269
|
|
|
@@ -306,10 +306,10 @@ Create a worktree
|
|
|
306
306
|
→ By the time the user or AI starts the project, dependencies are usually ready
|
|
307
307
|
```
|
|
308
308
|
|
|
309
|
-
Asynchronous initialization is started
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
309
|
+
Asynchronous initialization is started by the normal `post-checkout` hook or by the
|
|
310
|
+
Monitor Reconciler when it discovers an unregistered worktree. The Reconciler does
|
|
311
|
+
not process registered worktrees again, and each command's `skip_if` marker provides
|
|
312
|
+
additional protection against repeated setup. `wte sync` does not run initializers.
|
|
313
313
|
|
|
314
314
|
## Commands supported by `wte`
|
|
315
315
|
|
|
@@ -235,8 +235,8 @@ minimal.
|
|
|
235
235
|
The Reconciler:
|
|
236
236
|
|
|
237
237
|
1. Runs `git worktree list --porcelain` to retrieve the actual list of worktrees.
|
|
238
|
-
2. Compares it with `ports.json`, then assigns ports, mounts secrets,
|
|
239
|
-
files for unregistered worktrees.
|
|
238
|
+
2. Compares it with `ports.json`, then assigns ports, mounts secrets, generates
|
|
239
|
+
files, and starts configured initializers for unregistered worktrees.
|
|
240
240
|
|
|
241
241
|
After adding a profile or changing a `main_worktree` path, run this command again:
|
|
242
242
|
|
|
@@ -279,10 +279,10 @@ Create a worktree
|
|
|
279
279
|
→ By the time the user or AI starts the project, dependencies are usually ready
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
-
Asynchronous initialization is started
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
282
|
+
Asynchronous initialization is started by the normal `post-checkout` hook or by the
|
|
283
|
+
Monitor Reconciler when it discovers an unregistered worktree. The Reconciler does
|
|
284
|
+
not process registered worktrees again, and each command's `skip_if` marker provides
|
|
285
|
+
additional protection against repeated setup. `wte sync` does not run initializers.
|
|
286
286
|
|
|
287
287
|
## Commands supported by `wte`
|
|
288
288
|
|
|
@@ -188,7 +188,7 @@ wte monitor enable
|
|
|
188
188
|
Reconciler 会:
|
|
189
189
|
|
|
190
190
|
1. 执行 `git worktree list --porcelain` 获取真实 Worktree 列表。
|
|
191
|
-
2. 与 `ports.json` 对比,为尚未注册的 Worktree 分配端口、挂载 Secrets
|
|
191
|
+
2. 与 `ports.json` 对比,为尚未注册的 Worktree 分配端口、挂载 Secrets、生成文件并启动配置的初始化命令。
|
|
192
192
|
|
|
193
193
|
新增 Profile 或修改 `main_worktree` 路径后,需要再次执行:
|
|
194
194
|
|
|
@@ -230,7 +230,7 @@ init:
|
|
|
230
230
|
→ 用户或 AI 启动项目时,依赖通常已经准备完成
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
|
|
233
|
+
异步初始化由正常的 `post-checkout` Hook 启动;当 Monitor Reconciler 发现尚未注册的 Worktree 时也会启动。Reconciler 不会重复处理已注册的 Worktree,同时每条命令的 `skip_if` 标记可进一步避免重复初始化。`wte sync` 不会执行初始化命令。
|
|
234
234
|
|
|
235
235
|
## `wte` 支持的命令
|
|
236
236
|
|
|
@@ -53,9 +53,9 @@ writes:
|
|
|
53
53
|
PORT=${backend}
|
|
54
54
|
CORS_ORIGIN=http://127.0.0.1:${frontend}
|
|
55
55
|
|
|
56
|
-
# Optional post-checkout
|
|
57
|
-
# executed directly in the background.
|
|
58
|
-
# is resolved relative to cwd.
|
|
56
|
+
# Optional worktree initializers started by post-checkout or the Monitor Reconciler.
|
|
57
|
+
# Commands are trusted local configuration executed directly in the background.
|
|
58
|
+
# args are appended to command, and skip_if is resolved relative to cwd.
|
|
59
59
|
init:
|
|
60
60
|
- command: [npm]
|
|
61
61
|
args: [install]
|
|
@@ -110,7 +110,10 @@ def reconcile_once(paths: AppPaths) -> ReconcileResult:
|
|
|
110
110
|
# Git may publish common-dir metadata before checkout is complete.
|
|
111
111
|
if worktree_root(candidate) != candidate:
|
|
112
112
|
raise WteError(f"worktree root is not stable yet: {candidate}")
|
|
113
|
-
|
|
113
|
+
# The reconciler is the fallback for sandboxed Git clients that
|
|
114
|
+
# cannot invoke the host's post-checkout hook, so it must perform
|
|
115
|
+
# the same asynchronous initialization for a new worktree.
|
|
116
|
+
result = apply_worktree(paths, candidate, setup=True)
|
|
114
117
|
if result is None:
|
|
115
118
|
continue
|
|
116
119
|
print_apply_result(result)
|
|
@@ -32,7 +32,7 @@ def test_init_template_is_commented_and_not_an_active_yaml_profile(app_paths):
|
|
|
32
32
|
assert "# Port IDs form one contiguous block" in text
|
|
33
33
|
assert "# Optional local secret files" in text
|
|
34
34
|
assert "# Optional generated files" in text
|
|
35
|
-
assert "# Optional
|
|
35
|
+
assert "# Optional worktree initializers" in text
|
|
36
36
|
assert "$HOME/.config/example-app/frontend.env" in text
|
|
37
37
|
assert "$HOME/.config/example-app/backend.env" in text
|
|
38
38
|
assert "cwd: apps/frontend" in text
|
|
@@ -55,6 +55,30 @@ def test_reconciler_projects_only_unregistered_worktrees(
|
|
|
55
55
|
assert (linked / "generated.env").exists()
|
|
56
56
|
|
|
57
57
|
|
|
58
|
+
def test_reconciler_runs_initializers_for_unregistered_worktrees(
|
|
59
|
+
app_paths, git_worktrees, monkeypatch
|
|
60
|
+
):
|
|
61
|
+
main, linked = git_worktrees
|
|
62
|
+
(app_paths.profiles / "example.yaml").write_text(
|
|
63
|
+
"name: example\n"
|
|
64
|
+
f"match:\n main_worktree: {main}\n"
|
|
65
|
+
"ports:\n - id: web\n"
|
|
66
|
+
"init:\n - command: [tool]\n cwd: .\n"
|
|
67
|
+
)
|
|
68
|
+
monkeypatch.setattr("worktree_env.registry.port_is_free", lambda _port: True)
|
|
69
|
+
initialized = []
|
|
70
|
+
monkeypatch.setattr(
|
|
71
|
+
"worktree_env.projector.run_initializers",
|
|
72
|
+
lambda _profile, root: initialized.append(root),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
reconcile_once(app_paths)
|
|
76
|
+
reconcile_once(app_paths)
|
|
77
|
+
|
|
78
|
+
assert set(initialized) == {main.resolve(), linked.resolve()}
|
|
79
|
+
assert len(initialized) == 2
|
|
80
|
+
|
|
81
|
+
|
|
58
82
|
def test_launch_agent_watches_common_git_metadata(
|
|
59
83
|
app_paths, tmp_path, monkeypatch
|
|
60
84
|
):
|
|
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
|