claude-dev-env 7.5.0 → 7.6.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/.agents/skills/everything-search/scripts/everything_search.py +11 -0
- package/.agents/skills/everything-search/scripts/test_everything_search.py +1 -0
- package/.agents/skills/fresh-branch/SKILL.md +1 -0
- package/.agents/skills/fresh-branch/scripts/fresh_branch_git_commands.py +3 -0
- package/.agents/skills/fresh-branch/scripts/subprocess_window_access.py +43 -0
- package/.agents/skills/session-continuity/README.md +19 -9
- package/.agents/skills/syncing-submodules/SKILL.md +1 -0
- package/.agents/skills/syncing-submodules/scripts/submodule_sync.py +4 -0
- package/.agents/skills/syncing-submodules/scripts/subprocess_window_access.py +43 -0
- package/.agents/skills/test-runner/SKILL.md +1 -0
- package/.agents/skills/test-runner/scripts/preflight_checks.py +5 -0
- package/.agents/skills/test-runner/scripts/run_tests.py +11 -0
- package/.agents/skills/test-runner/scripts/subprocess_window_access.py +43 -0
- package/.agents/skills/test-runner/scripts/test_run_tests.py +9 -7
- package/_shared/pr-loop/scripts/check_bugbot_ci.py +3 -0
- package/_shared/pr-loop/scripts/check_convergence_gates.py +3 -0
- package/_shared/pr-loop/scripts/check_pending_reviews.py +3 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/added_line_maps.py +3 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/baseline_import_isolation.py +3 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/git_blob_readers.py +5 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/git_file_sets.py +4 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_regression.py +3 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_running.py +3 -0
- package/_shared/pr-loop/scripts/codex_usage_probe.py +3 -0
- package/_shared/pr-loop/scripts/copilot_quota.py +3 -0
- package/_shared/pr-loop/scripts/fetch_copilot_reviews.py +3 -0
- package/_shared/pr-loop/scripts/fix_hookspath.py +7 -0
- package/_shared/pr-loop/scripts/post_fix_reply.py +4 -0
- package/_shared/pr-loop/scripts/preflight.py +7 -0
- package/_shared/pr-loop/scripts/preflight_self_heal.py +5 -0
- package/_shared/pr-loop/scripts/run_codex_review.py +3 -0
- package/_shared/pr-loop/scripts/subprocess_window_access.py +41 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +5 -0
- package/_shared/process-tree/scripts/process_tree_kill.py +3 -0
- package/_shared/process-tree/scripts/subprocess_window_access.py +41 -0
- package/bin/install-constants.mjs +4 -2
- package/bin/install-session-continuity.mjs +73 -30
- package/bin/install-session-continuity.test.mjs +52 -1
- package/bin/install.cursor-rules.test.mjs +57 -15
- package/bin/install.mjs +80 -15
- package/bin/install.test.mjs +57 -0
- package/bin/pstack-model-preferences.claude.json +23 -0
- package/hooks/advisory/pr_done_reminder.py +7 -0
- package/hooks/advisory/refactor_guard.py +8 -0
- package/hooks/advisory/test_pr_done_reminder.py +21 -0
- package/hooks/advisory/test_refactor_guard.py +40 -0
- package/hooks/blocking/block_main_commit.py +4 -0
- package/hooks/blocking/code_rules_comments.py +39 -5
- package/hooks/blocking/pii_prevention_blocker_parts/repository_exemption.py +3 -0
- package/hooks/blocking/precommit_code_rules_gate.py +3 -0
- package/hooks/blocking/tdd_enforcer_parts/content_analysis.py +19 -3
- package/hooks/blocking/tdd_enforcer_parts/git_tracking.py +4 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/test_content_analysis.py +25 -0
- package/hooks/blocking/test_code_rules_enforcer_comment_string_awareness.py +27 -0
- package/hooks/blocking/test_code_rules_enforcer_exempt_marker_chained.py +10 -0
- package/hooks/git-hooks/git_hooks_constants/verification_notice_constants.py +0 -2
- package/hooks/git-hooks/pull_request_handoff.py +3 -0
- package/hooks/git-hooks/subprocess_window_access.py +41 -0
- package/hooks/git-hooks/test_verification_start.py +4 -0
- package/hooks/git-hooks/verification_notice_context.py +3 -0
- package/hooks/git-hooks/verification_start.py +7 -8
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +2 -0
- package/hooks/hooks_constants/subprocess_window.py +141 -0
- package/hooks/hooks_constants/subprocess_window_constants.py +9 -0
- package/hooks/hooks_constants/test_code_rules_enforcer_constants.py +6 -0
- package/hooks/hooks_constants/test_subprocess_window.py +128 -0
- package/hooks/lifecycle/enter_worktree_origin_prefetch.py +3 -0
- package/hooks/validation/mypy_validator.py +4 -0
- package/hooks/validators/README.md +1 -0
- package/hooks/validators/git_checks.py +4 -0
- package/hooks/validators/health_check.py +3 -0
- package/hooks/validators/hook_timing_harness.py +3 -0
- package/hooks/validators/mypy_integration.py +4 -0
- package/hooks/validators/ruff_integration.py +6 -0
- package/hooks/validators/run_all_validators.py +7 -0
- package/hooks/validators/subprocess_window_access.py +41 -0
- package/hooks/workflow/auto_formatter.py +8 -0
- package/hooks/workflow/test_auto_formatter.py +39 -0
- package/package.json +1 -1
- package/rules/pstack-models.md +4 -3
- package/scripts/automatic_advisory/checkout.py +8 -1
- package/scripts/automatic_advisory/cli.py +9 -3
- package/scripts/automatic_advisory/config/constants.py +0 -2
- package/scripts/automatic_advisory/execution.py +7 -1
- package/scripts/automatic_advisory/git.py +9 -1
- package/scripts/automatic_advisory/process_host.py +3 -0
- package/scripts/claude_chain_runner.py +3 -0
- package/scripts/gh_artifact_upload.py +3 -0
- package/scripts/grok_headless_runner.py +3 -0
- package/scripts/grok_patch_artifacts.py +4 -0
- package/scripts/grok_worker_preflight.py +3 -0
- package/scripts/invoke_code_review.py +3 -0
- package/scripts/local_verification/command_runner.py +3 -0
- package/scripts/local_verification/git_state.py +3 -0
- package/scripts/policy_lint/adapter_detectors.py +48 -2
- package/scripts/policy_lint/adapter_pairing.py +150 -2
- package/scripts/policy_lint/adapters.py +46 -4
- package/scripts/policy_lint/config/approved_test_pairs.py +25 -9
- package/scripts/policy_lint/config/constants.py +3 -0
- package/scripts/policy_lint/registry.py +1 -1
- package/scripts/policy_lint/selection_git.py +11 -0
- package/scripts/repository_checks/config/constants.py +5 -0
- package/scripts/repository_checks/config/policy_document.py +19 -0
- package/scripts/repository_checks/email_exemptions.py +14 -71
- package/scripts/repository_checks/path_exemptions.py +35 -0
- package/scripts/repository_checks/policy_document.py +120 -0
- package/scripts/repository_checks/tracked_secrets.py +27 -4
- package/scripts/setup_project_paths.py +3 -0
- package/scripts/spawn_grok_batch.py +3 -0
- package/scripts/subprocess_window_access.py +41 -0
- package/scripts/test_dispatcher_profile_import.py +4 -0
- package/scripts/tests/test_automatic_advisory_window_flags.py +17 -11
- package/scripts/tests/test_email_exemptions.py +37 -0
- package/scripts/tests/test_path_exemptions.py +164 -0
- package/scripts/tests/test_policy_document.py +104 -0
- package/scripts/tests/test_policy_lint_rules_function_length_scope.py +101 -0
- package/scripts/tests/test_policy_lint_rules_pairing.py +375 -0
- package/scripts/tests/test_policy_lint_rules_registry.py +116 -0
- package/scripts/tests/test_policy_lint_selection.py +34 -0
- package/scripts/tests/test_subprocess_window_access.py +118 -0
- package/scripts/tests/test_tracked_secrets.py +79 -0
- package/scripts/validate_instruction_pairs.py +3 -0
- package/scripts/verify_installable_package.py +5 -0
- package/scripts/automatic_advisory/window_flags.py +0 -41
- package/scripts/repository_checks/config/email_exemptions.py +0 -10
|
@@ -25,6 +25,16 @@ from everything_search_command_constants.config.constants import (
|
|
|
25
25
|
UTF8_ENCODING,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
+
_subprocess_window_hooks_directory = ""
|
|
29
|
+
for each_ancestor_directory in Path(__file__).resolve().parents:
|
|
30
|
+
if (each_ancestor_directory / "hooks" / "hooks_constants").is_dir():
|
|
31
|
+
_subprocess_window_hooks_directory = str(each_ancestor_directory / "hooks")
|
|
32
|
+
break
|
|
33
|
+
if _subprocess_window_hooks_directory not in sys.path:
|
|
34
|
+
sys.path.append(_subprocess_window_hooks_directory)
|
|
35
|
+
|
|
36
|
+
from hooks_constants.subprocess_window import hidden_window_creation_flags
|
|
37
|
+
|
|
28
38
|
|
|
29
39
|
class RegistryRunFatal(ValueError):
|
|
30
40
|
"""Stop the run when the project-path registry is unreadable or invalid."""
|
|
@@ -134,6 +144,7 @@ def _run_search(
|
|
|
134
144
|
encoding=UTF8_ENCODING,
|
|
135
145
|
shell=False,
|
|
136
146
|
text=True,
|
|
147
|
+
creationflags=hidden_window_creation_flags(),
|
|
137
148
|
)
|
|
138
149
|
except OSError as error:
|
|
139
150
|
search_stderr.write(f"{error}\n")
|
|
@@ -121,6 +121,7 @@ Further edits for the new branch belong in `worktree_path`, not in the caller's
|
|
|
121
121
|
| `CLAUDE.md` | Package map for agents browsing the skill folder |
|
|
122
122
|
| `scripts/create_fresh_branch.py` | **Execute** — deterministic fetch + worktree branch CLI |
|
|
123
123
|
| `scripts/fresh_branch_git_commands.py` | Git command helpers behind the CLI (fetch, ref checks, worktree add) |
|
|
124
|
+
| `scripts/subprocess_window_access.py` | Deployed-path shim re-exporting the hidden-window helpers |
|
|
124
125
|
| `scripts/test_create_fresh_branch.py` | Real-repo tests for agent/path/CLI behavior |
|
|
125
126
|
| `scripts/test_fresh_branch_git_commands.py` | Real-repo tests for the git command helpers |
|
|
126
127
|
| `scripts/fresh_branch_scripts_constants/` | Named constants for the CLI |
|
|
@@ -46,6 +46,8 @@ from fresh_branch_scripts_constants.fresh_branch_cli_constants import (
|
|
|
46
46
|
GIT_WORKTREE_ADD,
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
50
|
+
|
|
49
51
|
|
|
50
52
|
def run_git(
|
|
51
53
|
all_git_arguments: list[str],
|
|
@@ -66,6 +68,7 @@ def run_git(
|
|
|
66
68
|
check=False,
|
|
67
69
|
capture_output=True,
|
|
68
70
|
text=True,
|
|
71
|
+
creationflags=hidden_window_creation_flags(),
|
|
69
72
|
)
|
|
70
73
|
|
|
71
74
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Reach the hidden-window helpers from the scripts this directory deploys.
|
|
2
|
+
|
|
3
|
+
The installer copies this directory into a profile that holds no installed
|
|
4
|
+
Python distribution, and this repository's own tests run the deployed scripts
|
|
5
|
+
under ``python -S -E``, which hides every installed package from the child
|
|
6
|
+
process. On both routes ``hooks_constants`` is reachable only through the
|
|
7
|
+
deployed ``hooks`` directory, so this module puts that directory on
|
|
8
|
+
``sys.path`` and re-exports the helpers a caller asks for::
|
|
9
|
+
|
|
10
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
11
|
+
|
|
12
|
+
The directory goes on the end of ``sys.path``. ``PathFinder`` runs ahead of
|
|
13
|
+
every editable-install finder, so a trailing entry still selects the deployed
|
|
14
|
+
copy, and the head of ``sys.path`` stays exactly as the caller left it. A
|
|
15
|
+
caller that prepended its own roots keeps them first.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
_subprocess_window_hooks_directory = ""
|
|
24
|
+
for each_ancestor_directory in Path(__file__).resolve().parents:
|
|
25
|
+
if (each_ancestor_directory / "hooks" / "hooks_constants").is_dir():
|
|
26
|
+
_subprocess_window_hooks_directory = str(each_ancestor_directory / "hooks")
|
|
27
|
+
break
|
|
28
|
+
if _subprocess_window_hooks_directory not in sys.path:
|
|
29
|
+
sys.path.append(_subprocess_window_hooks_directory)
|
|
30
|
+
|
|
31
|
+
from hooks_constants.subprocess_window import (
|
|
32
|
+
HiddenWindowStartupInfo,
|
|
33
|
+
detached_hidden_window_creation_flags,
|
|
34
|
+
hidden_window_creation_flags,
|
|
35
|
+
inherited_stream_startup_info,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"HiddenWindowStartupInfo",
|
|
40
|
+
"detached_hidden_window_creation_flags",
|
|
41
|
+
"hidden_window_creation_flags",
|
|
42
|
+
"inherited_stream_startup_info",
|
|
43
|
+
]
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Session continuity companion
|
|
2
2
|
|
|
3
3
|
Status: draft implementation. Claude, Codex, and Cursor adapters have
|
|
4
|
-
repository-level contract tests.
|
|
4
|
+
repository-level contract tests. Claude installed-host automatic activation is
|
|
5
|
+
verified: a headless `claude -p` session on Claude Code 2.1.268 created a new
|
|
6
|
+
session-scope record carrying the `automatic` flag, with no user invocation.
|
|
7
|
+
Codex and Cursor installed-host activation, post-compaction reload, and agent
|
|
5
8
|
compliance remain unverified.
|
|
6
9
|
|
|
7
10
|
Every supported host activates Poteto Mode automatically when a session starts
|
|
@@ -27,21 +30,28 @@ pstack manifest refresher exposes namespaced Claude skills and leaves pstack
|
|
|
27
30
|
content with its existing owner. The companion edits none of that source,
|
|
28
31
|
manifest, invocation code, or model policy.
|
|
29
32
|
|
|
30
|
-
From this checkout, run the full existing installer
|
|
33
|
+
From this checkout, run the full existing installer:
|
|
31
34
|
|
|
32
35
|
```sh
|
|
33
36
|
node packages/claude-dev-env/bin/install.mjs
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The full installer publishes this skill under the canonical agents home and
|
|
40
|
+
registers its hooks in every host configuration the install root resolves. No
|
|
41
|
+
second command is needed. A selective `--only <group>` install skips both steps,
|
|
42
|
+
and a plugin-only installation needs the canonical installed skill first. For
|
|
43
|
+
either of those, or to configure one host alone, run the focused setup:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
34
46
|
node packages/claude-dev-env/bin/install-session-continuity.mjs
|
|
35
47
|
```
|
|
36
48
|
|
|
37
|
-
The
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
draft. Use the full install above. Plugin-only installations need the same
|
|
41
|
-
canonical installed skill before this setup can run.
|
|
49
|
+
The focused setup defaults to `claude codex cursor`. Pass one or more host names
|
|
50
|
+
to configure that subset alone. Registration is idempotent, so running it after a
|
|
51
|
+
full install reports each host as already configured.
|
|
42
52
|
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
An uninstall removes the companion's registrations along with its files, so no
|
|
54
|
+
host keeps a hook pointing at a script that is gone.
|
|
45
55
|
It uses `bin/resolve-install-root.mjs`, including `CLAUDE_CONFIG_DIR` and
|
|
46
56
|
`CODEX_HOME`. It merges only its own hook groups into Claude `settings.json` and
|
|
47
57
|
Codex `hooks.json`, preserves other settings, writes a one-time backup before
|
|
@@ -89,6 +89,7 @@ If `/pr-title-description` is not installed, report `pull_request_url` and finis
|
|
|
89
89
|
| `reference/run-tasks.md` | Task seeds for each repository-changing run |
|
|
90
90
|
| `scripts/sync_parent_pointer.py` | Execute the parent pointer sync and return one JSON result |
|
|
91
91
|
| `scripts/submodule_sync.py` | Own the Git operation and typed sync report |
|
|
92
|
+
| `scripts/subprocess_window_access.py` | Re-export the hidden-window helpers from the deployed hooks directory |
|
|
92
93
|
| `scripts/test_sync_parent_pointer.py` | Prove command parsing, JSON output, and hook deletion |
|
|
93
94
|
| `scripts/test_submodule_sync.py` | Prove exact commits, preserved staging, no-op states, and failures |
|
|
94
95
|
| `scripts/submodule_sync_constants/__init__.py` | Mark the constants package |
|
|
@@ -46,6 +46,8 @@ from submodule_sync_constants.config.constants import (
|
|
|
46
46
|
UTF8_ENCODING,
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
50
|
+
|
|
49
51
|
|
|
50
52
|
class SyncStatus(StrEnum):
|
|
51
53
|
"""States reported by one parent-pointer sync."""
|
|
@@ -123,6 +125,7 @@ def _execute_git(
|
|
|
123
125
|
errors=DECODE_ERRORS_POLICY,
|
|
124
126
|
env=_build_child_environment(),
|
|
125
127
|
timeout=GIT_COMMAND_TIMEOUT_SECONDS,
|
|
128
|
+
creationflags=hidden_window_creation_flags(),
|
|
126
129
|
)
|
|
127
130
|
except subprocess.TimeoutExpired as error:
|
|
128
131
|
raise _GitCommandFailure(
|
|
@@ -179,6 +182,7 @@ def lookup_pull_request_url(repository: Path) -> str | None:
|
|
|
179
182
|
errors=DECODE_ERRORS_POLICY,
|
|
180
183
|
env=_build_child_environment(),
|
|
181
184
|
timeout=GH_COMMAND_TIMEOUT_SECONDS,
|
|
185
|
+
creationflags=hidden_window_creation_flags(),
|
|
182
186
|
)
|
|
183
187
|
except (OSError, subprocess.SubprocessError):
|
|
184
188
|
return None
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Reach the hidden-window helpers from the scripts this directory deploys.
|
|
2
|
+
|
|
3
|
+
The installer copies this directory into a profile that holds no installed
|
|
4
|
+
Python distribution, and this repository's own tests run the deployed scripts
|
|
5
|
+
under ``python -S -E``, which hides every installed package from the child
|
|
6
|
+
process. On both routes ``hooks_constants`` is reachable only through the
|
|
7
|
+
deployed ``hooks`` directory, so this module puts that directory on
|
|
8
|
+
``sys.path`` and re-exports the helpers a caller asks for::
|
|
9
|
+
|
|
10
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
11
|
+
|
|
12
|
+
The directory goes on the end of ``sys.path``. ``PathFinder`` runs ahead of
|
|
13
|
+
every editable-install finder, so a trailing entry still selects the deployed
|
|
14
|
+
copy, and the head of ``sys.path`` stays exactly as the caller left it. A
|
|
15
|
+
caller that prepended its own roots keeps them first.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
_subprocess_window_hooks_directory = ""
|
|
24
|
+
for each_ancestor_directory in Path(__file__).resolve().parents:
|
|
25
|
+
if (each_ancestor_directory / "hooks" / "hooks_constants").is_dir():
|
|
26
|
+
_subprocess_window_hooks_directory = str(each_ancestor_directory / "hooks")
|
|
27
|
+
break
|
|
28
|
+
if _subprocess_window_hooks_directory not in sys.path:
|
|
29
|
+
sys.path.append(_subprocess_window_hooks_directory)
|
|
30
|
+
|
|
31
|
+
from hooks_constants.subprocess_window import (
|
|
32
|
+
HiddenWindowStartupInfo,
|
|
33
|
+
detached_hidden_window_creation_flags,
|
|
34
|
+
hidden_window_creation_flags,
|
|
35
|
+
inherited_stream_startup_info,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"HiddenWindowStartupInfo",
|
|
40
|
+
"detached_hidden_window_creation_flags",
|
|
41
|
+
"hidden_window_creation_flags",
|
|
42
|
+
"inherited_stream_startup_info",
|
|
43
|
+
]
|
|
@@ -64,6 +64,7 @@ run migrations, or repair a failed preflight.
|
|
|
64
64
|
- `SKILL.md` covers invocation, checks, and the command boundary.
|
|
65
65
|
- `scripts/run_tests.py` parses the command, runs preflight, and launches the child.
|
|
66
66
|
- `scripts/preflight_checks.py` runs Django and Playwright readiness checks.
|
|
67
|
+
- `scripts/subprocess_window_access.py` re-exports the hidden-window helpers from the deployed hooks directory.
|
|
67
68
|
- `scripts/test_run_tests.py` covers the command and preflight.
|
|
68
69
|
- `scripts/test_preflight_checks.py` covers the readiness checks.
|
|
69
70
|
- `scripts/test_runner_constants/` holds command names, messages, and limits.
|
|
@@ -48,6 +48,8 @@ from test_runner_constants.config.constants import (
|
|
|
48
48
|
UNREACHABLE_ERROR_TEMPLATE,
|
|
49
49
|
)
|
|
50
50
|
|
|
51
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
52
|
+
|
|
51
53
|
try:
|
|
52
54
|
import psutil
|
|
53
55
|
except ImportError:
|
|
@@ -70,6 +72,7 @@ def check_server_health(target_url: str) -> str | None:
|
|
|
70
72
|
text=True,
|
|
71
73
|
timeout=HEALTH_CHECK_TIMEOUT_SECONDS,
|
|
72
74
|
check=False,
|
|
75
|
+
creationflags=hidden_window_creation_flags(),
|
|
73
76
|
)
|
|
74
77
|
http_status_code = int(completed_process.stdout.strip())
|
|
75
78
|
except (OSError, ValueError, subprocess.TimeoutExpired):
|
|
@@ -215,6 +218,7 @@ def _read_process_listing() -> str | None:
|
|
|
215
218
|
text=True,
|
|
216
219
|
timeout=PROCESS_CURL_TIMEOUT_SECONDS,
|
|
217
220
|
check=False,
|
|
221
|
+
creationflags=hidden_window_creation_flags(),
|
|
218
222
|
)
|
|
219
223
|
except (OSError, subprocess.TimeoutExpired):
|
|
220
224
|
return None
|
|
@@ -359,6 +363,7 @@ def _run_preparation(
|
|
|
359
363
|
text=True,
|
|
360
364
|
timeout=BUILD_TIMEOUT_SECONDS,
|
|
361
365
|
check=False,
|
|
366
|
+
creationflags=hidden_window_creation_flags(),
|
|
362
367
|
)
|
|
363
368
|
except (OSError, subprocess.TimeoutExpired):
|
|
364
369
|
return True
|
|
@@ -55,6 +55,16 @@ from test_runner_constants.config.constants import (
|
|
|
55
55
|
SERVER_URL_PATTERN,
|
|
56
56
|
)
|
|
57
57
|
|
|
58
|
+
_subprocess_window_hooks_directory = ""
|
|
59
|
+
for each_ancestor_directory in Path(__file__).resolve().parents:
|
|
60
|
+
if (each_ancestor_directory / "hooks" / "hooks_constants").is_dir():
|
|
61
|
+
_subprocess_window_hooks_directory = str(each_ancestor_directory / "hooks")
|
|
62
|
+
break
|
|
63
|
+
if _subprocess_window_hooks_directory not in sys.path:
|
|
64
|
+
sys.path.append(_subprocess_window_hooks_directory)
|
|
65
|
+
|
|
66
|
+
from hooks_constants.subprocess_window import inherited_stream_startup_info
|
|
67
|
+
|
|
58
68
|
build_frontend = preflight_checks.build_frontend
|
|
59
69
|
check_django_database = preflight_checks.check_django_database
|
|
60
70
|
check_runserver_port_conflicts = preflight_checks.check_runserver_port_conflicts
|
|
@@ -277,6 +287,7 @@ def run_child_process(
|
|
|
277
287
|
list(all_child_arguments),
|
|
278
288
|
cwd=project_root,
|
|
279
289
|
check=False,
|
|
290
|
+
startupinfo=inherited_stream_startup_info(),
|
|
280
291
|
)
|
|
281
292
|
except OSError as error:
|
|
282
293
|
print(ERROR_CHILD_LAUNCH_TEMPLATE.format(error), file=sys.stderr)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Reach the hidden-window helpers from the scripts this directory deploys.
|
|
2
|
+
|
|
3
|
+
The installer copies this directory into a profile that holds no installed
|
|
4
|
+
Python distribution, and this repository's own tests run the deployed scripts
|
|
5
|
+
under ``python -S -E``, which hides every installed package from the child
|
|
6
|
+
process. On both routes ``hooks_constants`` is reachable only through the
|
|
7
|
+
deployed ``hooks`` directory, so this module puts that directory on
|
|
8
|
+
``sys.path`` and re-exports the helpers a caller asks for::
|
|
9
|
+
|
|
10
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
11
|
+
|
|
12
|
+
The directory goes on the end of ``sys.path``. ``PathFinder`` runs ahead of
|
|
13
|
+
every editable-install finder, so a trailing entry still selects the deployed
|
|
14
|
+
copy, and the head of ``sys.path`` stays exactly as the caller left it. A
|
|
15
|
+
caller that prepended its own roots keeps them first.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
_subprocess_window_hooks_directory = ""
|
|
24
|
+
for each_ancestor_directory in Path(__file__).resolve().parents:
|
|
25
|
+
if (each_ancestor_directory / "hooks" / "hooks_constants").is_dir():
|
|
26
|
+
_subprocess_window_hooks_directory = str(each_ancestor_directory / "hooks")
|
|
27
|
+
break
|
|
28
|
+
if _subprocess_window_hooks_directory not in sys.path:
|
|
29
|
+
sys.path.append(_subprocess_window_hooks_directory)
|
|
30
|
+
|
|
31
|
+
from hooks_constants.subprocess_window import (
|
|
32
|
+
HiddenWindowStartupInfo,
|
|
33
|
+
detached_hidden_window_creation_flags,
|
|
34
|
+
hidden_window_creation_flags,
|
|
35
|
+
inherited_stream_startup_info,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"HiddenWindowStartupInfo",
|
|
40
|
+
"detached_hidden_window_creation_flags",
|
|
41
|
+
"hidden_window_creation_flags",
|
|
42
|
+
"inherited_stream_startup_info",
|
|
43
|
+
]
|
|
@@ -128,13 +128,15 @@ def test_main_runs_plain_pytest_without_django_preflight(
|
|
|
128
128
|
)
|
|
129
129
|
|
|
130
130
|
assert exit_code == 7
|
|
131
|
-
assert all_calls ==
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
assert len(all_calls) == 1
|
|
132
|
+
recorded_call = dict(all_calls[0])
|
|
133
|
+
recorded_startup_information = recorded_call.pop("startupinfo")
|
|
134
|
+
assert recorded_call == {
|
|
135
|
+
"arguments": ["python", "-m", "pytest", "tests"],
|
|
136
|
+
"cwd": tmp_path.resolve(),
|
|
137
|
+
"check": False,
|
|
138
|
+
}
|
|
139
|
+
assert (recorded_startup_information is None) == (sys.platform != "win32")
|
|
138
140
|
|
|
139
141
|
|
|
140
142
|
def test_missing_django_database_stops_before_child_launch(
|
|
@@ -43,6 +43,8 @@ from pr_converge_skill_constants.constants import (
|
|
|
43
43
|
GH_CHECK_RUNS_PATH_TEMPLATE,
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
47
|
+
|
|
46
48
|
|
|
47
49
|
def _run_check_runs_api(
|
|
48
50
|
*, owner: str, repo: str, sha: str
|
|
@@ -62,6 +64,7 @@ def _run_check_runs_api(
|
|
|
62
64
|
encoding="utf-8",
|
|
63
65
|
errors="replace",
|
|
64
66
|
check=False,
|
|
67
|
+
creationflags=hidden_window_creation_flags(),
|
|
65
68
|
)
|
|
66
69
|
|
|
67
70
|
|
|
@@ -32,6 +32,8 @@ from pr_converge_scripts_constants.convergence_gate_constants import (
|
|
|
32
32
|
SHORT_SHA_LENGTH,
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
36
|
+
|
|
35
37
|
JsonObject = dict[str, object]
|
|
36
38
|
ReviewStateGroup = tuple[str, ...]
|
|
37
39
|
|
|
@@ -44,6 +46,7 @@ def _run_gh_command(all_arguments: list[str]) -> tuple[int, str]:
|
|
|
44
46
|
encoding="utf-8",
|
|
45
47
|
errors="replace",
|
|
46
48
|
check=False,
|
|
49
|
+
creationflags=hidden_window_creation_flags(),
|
|
47
50
|
)
|
|
48
51
|
return completed_process.returncode, completed_process.stdout
|
|
49
52
|
|
|
@@ -27,6 +27,8 @@ from pr_converge_skill_constants.constants import (
|
|
|
27
27
|
REVIEWS_PER_PAGE,
|
|
28
28
|
)
|
|
29
29
|
|
|
30
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
31
|
+
|
|
30
32
|
|
|
31
33
|
def fetch_pending_reviews(
|
|
32
34
|
*, owner: str, repo: str, number: int, user_filter: str | None = None
|
|
@@ -56,6 +58,7 @@ def fetch_pending_reviews(
|
|
|
56
58
|
encoding="utf-8",
|
|
57
59
|
errors="replace",
|
|
58
60
|
check=False,
|
|
61
|
+
creationflags=hidden_window_creation_flags(),
|
|
59
62
|
)
|
|
60
63
|
if completed_process.returncode != 0:
|
|
61
64
|
print(f"gh api error: {completed_process.stderr}", file=sys.stderr)
|
|
@@ -24,6 +24,8 @@ from code_rules_gate_parts.git_file_sets import (
|
|
|
24
24
|
)
|
|
25
25
|
from code_rules_gate_parts.violation_scoping import parse_added_line_numbers
|
|
26
26
|
|
|
27
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
28
|
+
|
|
27
29
|
|
|
28
30
|
def _run_git_text_capture(
|
|
29
31
|
repository_root: Path, all_git_arguments: list[str]
|
|
@@ -38,6 +40,7 @@ def _run_git_text_capture(
|
|
|
38
40
|
errors="replace",
|
|
39
41
|
check=False,
|
|
40
42
|
env=repository_environment(),
|
|
43
|
+
creationflags=hidden_window_creation_flags(),
|
|
41
44
|
)
|
|
42
45
|
|
|
43
46
|
|
|
@@ -49,6 +49,8 @@ from pr_loop_shared_constants.code_rules_gate_constants import (
|
|
|
49
49
|
PYTHONPATH_ENV_VAR,
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
53
|
+
|
|
52
54
|
|
|
53
55
|
def _resolved_directory(path_text: str) -> Path | None:
|
|
54
56
|
"""Return *path_text* resolved to an absolute path, or None when it is unusable."""
|
|
@@ -152,6 +154,7 @@ def _completed_import_root_probe(
|
|
|
152
154
|
text=True,
|
|
153
155
|
check=False,
|
|
154
156
|
timeout=BASELINE_IMPORT_PROBE_TIMEOUT_SECONDS,
|
|
157
|
+
creationflags=hidden_window_creation_flags(),
|
|
155
158
|
)
|
|
156
159
|
except subprocess.TimeoutExpired:
|
|
157
160
|
sys.stderr.write(
|
|
@@ -11,6 +11,8 @@ from pathlib import Path
|
|
|
11
11
|
|
|
12
12
|
from terminology_sweep import repository_environment
|
|
13
13
|
|
|
14
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
def read_prior_committed_content(
|
|
16
18
|
repository_root: Path, relative_path_posix: str, ref: str = "HEAD"
|
|
@@ -38,6 +40,7 @@ def read_prior_committed_content(
|
|
|
38
40
|
errors="replace",
|
|
39
41
|
check=False,
|
|
40
42
|
env=repository_environment(),
|
|
43
|
+
creationflags=hidden_window_creation_flags(),
|
|
41
44
|
)
|
|
42
45
|
if completed.returncode != 0:
|
|
43
46
|
return ""
|
|
@@ -61,6 +64,7 @@ def read_staged_content(repository_root: Path, relative_path_posix: str) -> str
|
|
|
61
64
|
capture_output=True,
|
|
62
65
|
check=False,
|
|
63
66
|
env=repository_environment(),
|
|
67
|
+
creationflags=hidden_window_creation_flags(),
|
|
64
68
|
)
|
|
65
69
|
if completed.returncode != 0:
|
|
66
70
|
return None
|
|
@@ -87,5 +91,6 @@ def staged_blob_exists(repository_root: Path, relative_path_posix: str) -> bool:
|
|
|
87
91
|
capture_output=True,
|
|
88
92
|
check=False,
|
|
89
93
|
env=repository_environment(),
|
|
94
|
+
creationflags=hidden_window_creation_flags(),
|
|
90
95
|
)
|
|
91
96
|
return completed.returncode == 0
|
|
@@ -19,6 +19,8 @@ from pr_loop_shared_constants.code_rules_gate_constants import (
|
|
|
19
19
|
)
|
|
20
20
|
from terminology_sweep import repository_environment
|
|
21
21
|
|
|
22
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
23
|
+
|
|
22
24
|
__all__ = [
|
|
23
25
|
"repository_environment",
|
|
24
26
|
"resolve_merge_base",
|
|
@@ -57,6 +59,7 @@ def _git_text_or_exit(
|
|
|
57
59
|
errors="replace",
|
|
58
60
|
check=False,
|
|
59
61
|
env=repository_environment(),
|
|
62
|
+
creationflags=hidden_window_creation_flags(),
|
|
60
63
|
)
|
|
61
64
|
if completed.returncode != 0:
|
|
62
65
|
sys.stderr.write(f"{failure_prefix}:\n{completed.stderr}\n")
|
|
@@ -86,6 +89,7 @@ def _git_bytes_or_exit(
|
|
|
86
89
|
capture_output=True,
|
|
87
90
|
check=False,
|
|
88
91
|
env=repository_environment(),
|
|
92
|
+
creationflags=hidden_window_creation_flags(),
|
|
89
93
|
)
|
|
90
94
|
if completed.returncode != 0:
|
|
91
95
|
stderr_text = completed.stderr.decode("utf-8", errors="replace")
|
|
@@ -66,6 +66,8 @@ from terminology_sweep import repository_environment
|
|
|
66
66
|
|
|
67
67
|
from code_rules_gate_parts import baseline_import_isolation, staged_test_running
|
|
68
68
|
|
|
69
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
70
|
+
|
|
69
71
|
TestIdentity = tuple[str, str]
|
|
70
72
|
|
|
71
73
|
|
|
@@ -93,6 +95,7 @@ def _run_git(
|
|
|
93
95
|
text=True,
|
|
94
96
|
check=False,
|
|
95
97
|
env=repository_environment(),
|
|
98
|
+
creationflags=hidden_window_creation_flags(),
|
|
96
99
|
)
|
|
97
100
|
|
|
98
101
|
|
|
@@ -59,6 +59,8 @@ from terminology_sweep import repository_environment
|
|
|
59
59
|
from code_rules_gate_parts.git_file_sets import paths_from_git_staged
|
|
60
60
|
from code_rules_gate_parts.wrapper_plumb_check import is_test_path
|
|
61
61
|
|
|
62
|
+
from subprocess_window_access import inherited_stream_startup_info
|
|
63
|
+
|
|
62
64
|
|
|
63
65
|
def _is_conftest_path(file_path: Path) -> bool:
|
|
64
66
|
"""Return True when *file_path* is a pytest ``conftest.py`` fixture module."""
|
|
@@ -411,6 +413,7 @@ def _pytest_batch_exit_code(
|
|
|
411
413
|
timeout=STAGED_PYTEST_TIMEOUT_SECONDS,
|
|
412
414
|
check=False,
|
|
413
415
|
env=environment,
|
|
416
|
+
startupinfo=inherited_stream_startup_info(),
|
|
414
417
|
)
|
|
415
418
|
if pytest_process.returncode == PYTEST_NO_TESTS_COLLECTED_EXIT_CODE:
|
|
416
419
|
return 0
|
|
@@ -118,6 +118,8 @@ from codex_review_scripts_constants.codex_usage_probe_constants import ( # noqa
|
|
|
118
118
|
WINDOWS_OS_NAME,
|
|
119
119
|
)
|
|
120
120
|
|
|
121
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
122
|
+
|
|
121
123
|
|
|
122
124
|
class AppServerExchange(Protocol):
|
|
123
125
|
"""Callable that sends JSON-RPC request objects and returns stdout lines."""
|
|
@@ -464,6 +466,7 @@ def _exchange_app_server_messages_via_subprocess(
|
|
|
464
466
|
encoding=UTF8_ENCODING,
|
|
465
467
|
shell=False,
|
|
466
468
|
start_new_session=should_start_new_session(),
|
|
469
|
+
creationflags=hidden_window_creation_flags(),
|
|
467
470
|
) as server_process:
|
|
468
471
|
server_stdin = server_process.stdin
|
|
469
472
|
server_stdout = server_process.stdout
|
|
@@ -46,6 +46,8 @@ from pr_loop_shared_constants.copilot_quota_constants import (
|
|
|
46
46
|
QUOTA_SNAPSHOTS_FIELD_NAME,
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
50
|
+
|
|
49
51
|
|
|
50
52
|
@dataclass(frozen=True)
|
|
51
53
|
class QuotaDecision:
|
|
@@ -86,6 +88,7 @@ def _run_gh(
|
|
|
86
88
|
errors="replace",
|
|
87
89
|
check=False,
|
|
88
90
|
env=process_environment,
|
|
91
|
+
creationflags=hidden_window_creation_flags(),
|
|
89
92
|
)
|
|
90
93
|
return completed_process.returncode, completed_process.stdout
|
|
91
94
|
|
|
@@ -25,6 +25,8 @@ from pr_converge_skill_constants.constants import (
|
|
|
25
25
|
REVIEWS_PER_PAGE,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
+
from subprocess_window_access import hidden_window_creation_flags
|
|
29
|
+
|
|
28
30
|
|
|
29
31
|
def fetch_copilot_reviews(
|
|
30
32
|
*, owner: str, repo: str, number: int
|
|
@@ -56,6 +58,7 @@ def fetch_copilot_reviews(
|
|
|
56
58
|
encoding="utf-8",
|
|
57
59
|
errors="replace",
|
|
58
60
|
check=False,
|
|
61
|
+
creationflags=hidden_window_creation_flags(),
|
|
59
62
|
)
|
|
60
63
|
if completed_process.returncode != 0:
|
|
61
64
|
print(f"gh api error: {completed_process.stderr}", file=sys.stderr)
|
|
@@ -17,6 +17,8 @@ from pr_loop_shared_constants.fix_hookspath_constants import ( # noqa: E402
|
|
|
17
17
|
)
|
|
18
18
|
from pr_loop_shared_constants.preflight_constants import GIT_DIRECTORY_NAME # noqa: E402
|
|
19
19
|
|
|
20
|
+
from subprocess_window_access import hidden_window_creation_flags, inherited_stream_startup_info
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
def resolve_canonical_hooks_directory(
|
|
22
24
|
all_environment_overrides: dict[str, str] | None,
|
|
@@ -74,6 +76,7 @@ def list_local_core_hooks_path_values(
|
|
|
74
76
|
errors="replace",
|
|
75
77
|
check=False,
|
|
76
78
|
env=all_environment_overrides,
|
|
79
|
+
creationflags=hidden_window_creation_flags(),
|
|
77
80
|
)
|
|
78
81
|
if completed_process.returncode != 0:
|
|
79
82
|
diagnostic_stderr = completed_process.stderr.strip()
|
|
@@ -115,6 +118,7 @@ def read_global_core_hooks_path(
|
|
|
115
118
|
errors="replace",
|
|
116
119
|
check=False,
|
|
117
120
|
env=all_environment_overrides,
|
|
121
|
+
creationflags=hidden_window_creation_flags(),
|
|
118
122
|
)
|
|
119
123
|
if completed_process.returncode != 0:
|
|
120
124
|
diagnostic_stderr = completed_process.stderr.strip()
|
|
@@ -156,6 +160,7 @@ def unset_local_core_hooks_path(
|
|
|
156
160
|
text=True,
|
|
157
161
|
check=False,
|
|
158
162
|
env=all_environment_overrides,
|
|
163
|
+
creationflags=hidden_window_creation_flags(),
|
|
159
164
|
)
|
|
160
165
|
return completed_process.returncode
|
|
161
166
|
|
|
@@ -181,6 +186,7 @@ def set_global_core_hooks_path(
|
|
|
181
186
|
text=True,
|
|
182
187
|
check=False,
|
|
183
188
|
env=all_environment_overrides,
|
|
189
|
+
creationflags=hidden_window_creation_flags(),
|
|
184
190
|
)
|
|
185
191
|
return completed_process.returncode
|
|
186
192
|
|
|
@@ -241,6 +247,7 @@ def rerun_preflight(
|
|
|
241
247
|
rerun_command,
|
|
242
248
|
check=False,
|
|
243
249
|
env=all_environment_overrides,
|
|
250
|
+
startupinfo=inherited_stream_startup_info(),
|
|
244
251
|
)
|
|
245
252
|
return completed_process.returncode
|
|
246
253
|
|