claude-dev-env 1.41.0 → 1.43.0
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/CLAUDE.md +8 -0
- package/_shared/pr-loop/scripts/_claude_permissions_common.py +232 -8
- package/_shared/pr-loop/scripts/code_rules_gate.py +293 -8
- package/_shared/pr-loop/scripts/fix_hookspath.py +96 -5
- package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +124 -20
- package/_shared/pr-loop/scripts/post_audit_thread.py +4 -4
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/claude_permissions_constants.py +90 -0
- package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/claude_settings_keys_constants.py +2 -0
- package/_shared/pr-loop/scripts/preflight.py +13 -31
- package/_shared/pr-loop/scripts/reviews_disabled.py +2 -16
- package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +76 -33
- package/_shared/pr-loop/scripts/tests/conftest.py +1 -51
- package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +385 -0
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +4 -2
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +37 -2
- package/_shared/pr-loop/scripts/tests/test_claude_settings_keys_constants.py +4 -2
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate_constants.py +4 -2
- package/_shared/pr-loop/scripts/tests/test_fix_hookspath_constants.py +6 -2
- package/_shared/pr-loop/scripts/tests/test_grant_project_claude_permissions.py +2 -2
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +1 -2
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +4 -2
- package/_shared/pr-loop/scripts/tests/test_preflight.py +17 -52
- package/_shared/pr-loop/scripts/tests/test_preflight_constants.py +6 -2
- package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +5 -3
- package/agents/pr-description-writer.md +50 -140
- package/docs/PR_DESCRIPTION_GUIDE.md +101 -102
- package/hooks/_gh_pr_author_swap_utils.py +1 -1
- package/hooks/blocking/bot_mention_comment_blocker.py +4 -10
- package/hooks/blocking/code_rules_enforcer.py +217 -99
- package/hooks/blocking/code_rules_path_utils.py +8 -1
- package/hooks/blocking/destructive_command_blocker.py +1 -1
- package/hooks/blocking/es_exe_path_rewriter.py +7 -13
- package/hooks/blocking/gh_body_arg_blocker.py +6 -1
- package/hooks/blocking/gh_pr_author_enforcer.py +5 -5
- package/hooks/blocking/gh_pr_author_restore.py +5 -5
- package/hooks/blocking/hedging_language_blocker.py +4 -10
- package/hooks/blocking/md_path_exemptions.py +205 -0
- package/hooks/blocking/md_to_html_blocker.py +48 -20
- package/hooks/blocking/pr_converge_bugteam_enforcer.py +5 -11
- package/hooks/blocking/pr_description_enforcer.py +626 -41
- package/hooks/blocking/question_to_user_enforcer.py +4 -10
- package/hooks/blocking/state_description_blocker.py +6 -12
- package/hooks/blocking/tdd_enforcer.py +1 -1
- package/hooks/blocking/test_bot_mention_comment_blocker.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer.py +3 -3
- package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -2
- package/hooks/blocking/test_code_rules_enforcer_comment_string_awareness.py +184 -0
- package/hooks/blocking/test_code_rules_enforcer_type_checking_scope.py +82 -0
- package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +29 -29
- package/hooks/blocking/test_gh_body_arg_blocker.py +7 -8
- package/hooks/blocking/test_gh_pr_author_enforcer.py +1 -1
- package/hooks/blocking/test_gh_pr_author_restore.py +1 -1
- package/hooks/blocking/test_hedging_language_blocker.py +2 -2
- package/hooks/blocking/test_md_to_html_blocker.py +463 -8
- package/hooks/blocking/test_pr_converge_bugteam_enforcer.py +1 -1
- package/hooks/blocking/test_pr_description_enforcer.py +1210 -13
- package/hooks/blocking/test_question_to_user_enforcer.py +1 -1
- package/hooks/blocking/windows_rmtree_blocker.py +5 -11
- package/hooks/diagnostic/hook_log_extractor.py +1 -1
- package/hooks/diagnostic/hook_log_init.py +1 -1
- package/hooks/diagnostic/hook_log_stop_wrapper.py +1 -1
- package/hooks/diagnostic/test_hook_log_extractor.py +1 -1
- package/hooks/diagnostic/test_hook_log_init.py +2 -2
- package/hooks/diagnostic/test_hook_log_stop_wrapper.py +1 -1
- package/hooks/git-hooks/gate_utils.py +1 -1
- package/hooks/git-hooks/pre_commit.py +1 -1
- package/hooks/git-hooks/pre_push.py +1 -1
- package/hooks/git-hooks/test_config.py +5 -5
- package/hooks/git-hooks/test_pre_push.py +6 -6
- package/hooks/{config → hooks_constants}/code_rules_enforcer_constants.py +37 -0
- package/hooks/hooks_constants/code_rules_path_utils_constants.py +28 -0
- package/hooks/hooks_constants/md_to_html_blocker_constants.py +82 -0
- package/hooks/{config → hooks_constants}/pr_converge_bugteam_enforcer_state.py +1 -1
- package/hooks/hooks_constants/pr_description_enforcer_constants.py +154 -0
- package/hooks/{config → hooks_constants}/pre_tool_use_stdin.py +1 -1
- package/hooks/{config → hooks_constants}/project_paths_reader.py +2 -2
- package/hooks/{config → hooks_constants}/test_banned_identifiers_constants.py +1 -1
- package/hooks/{config → hooks_constants}/test_dynamic_stderr_handler.py +1 -1
- package/hooks/{config → hooks_constants}/test_hardcoded_user_path_constants.py +1 -1
- package/hooks/{config → hooks_constants}/test_hook_log_extractor_constants.py +2 -2
- package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +110 -0
- package/hooks/{config → hooks_constants}/test_messages.py +2 -6
- package/hooks/{config → hooks_constants}/test_path_rewriter_constants.py +1 -1
- package/hooks/hooks_constants/test_pr_description_enforcer_constants.py +292 -0
- package/hooks/{config → hooks_constants}/test_pre_tool_use_stdin.py +2 -2
- package/hooks/{config → hooks_constants}/test_project_paths_reader.py +3 -3
- package/hooks/{config → hooks_constants}/test_session_env_cleanup_constants.py +1 -1
- package/hooks/{config → hooks_constants}/test_setup_project_paths_constants.py +2 -2
- package/hooks/{config → hooks_constants}/test_unused_module_import_constants.py +1 -1
- package/hooks/lifecycle/pr_converge_bugteam_skill_tracker.py +5 -11
- package/hooks/lifecycle/test_pr_converge_bugteam_skill_tracker.py +1 -1
- package/hooks/session/gh_pr_author_session_cleanup.py +5 -6
- package/hooks/session/session_env_cleanup.py +4 -10
- package/hooks/session/test_gh_pr_author_session_cleanup.py +1 -1
- package/hooks/session/test_untracked_repo_detector.py +2 -2
- package/hooks/session/untracked_repo_detector.py +6 -12
- package/hooks/test__gh_pr_author_swap_utils.py +1 -1
- package/hooks/validators/run_all_validators.py +16 -5
- package/hooks/validators/test_output_formatter.py +46 -0
- package/hooks/workflow/doc_gist_auto_publish.py +1 -1
- package/hooks/workflow/md_to_html_companion.py +8 -15
- package/hooks/workflow/test_md_to_html_companion.py +184 -23
- package/package.json +1 -1
- package/rules/ask-user-question-required.md +1 -1
- package/rules/vault-context.md +1 -1
- package/scripts/{config → dev_env_scripts_constants}/timing.py +1 -1
- package/scripts/setup_project_paths.py +49 -11
- package/scripts/sweep_empty_dirs.py +10 -1
- package/scripts/test_setup_project_paths.py +2 -2
- package/scripts/test_sweep_empty_dirs.py +2 -6
- package/skills/_shared/pr-loop/scripts/_path_resolver.py +1 -1
- package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +1 -1
- package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +1 -1
- package/skills/_shared/pr-loop/scripts/init_loop_state.py +1 -1
- package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +1 -1
- package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +2 -2
- package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +2 -2
- package/skills/bugteam/PROMPTS.md +1 -1
- package/skills/bugteam/SKILL.md +1 -1
- package/skills/bugteam/reference/github-pr-reviews.md +1 -1
- package/skills/bugteam/scripts/{_claude_permissions_common.py → _bugteam_permissions_common.py} +110 -13
- package/skills/bugteam/scripts/bugteam_code_rules_gate.py +1 -13
- package/skills/bugteam/scripts/bugteam_fix_hookspath.py +1 -16
- package/skills/bugteam/scripts/bugteam_preflight.py +1 -13
- package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +69 -0
- package/skills/bugteam/scripts/grant_project_claude_permissions.py +117 -12
- package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +1 -1
- package/skills/bugteam/scripts/reflow_skill_md.py +1 -1
- package/skills/bugteam/scripts/revoke_project_claude_permissions.py +71 -25
- package/skills/bugteam/scripts/{test__claude_permissions_common.py → test__bugteam_permissions_common.py} +4 -4
- package/skills/bugteam/scripts/test_agent_config_carveout.py +356 -0
- package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -26
- package/skills/bugteam/scripts/{test_claude_permissions_common.py → test_bugteam_permissions_common.py} +3 -66
- package/skills/bugteam/scripts/test_bugteam_preflight.py +2 -27
- package/skills/bugteam/scripts/windows_safe_rmtree.py +1 -1
- package/skills/doc-gist/SKILL.md +1 -1
- package/skills/doc-gist/scripts/gist_upload.py +1 -1
- package/skills/implement/SKILL.md +66 -0
- package/skills/implement/scripts/append_note.py +133 -0
- package/skills/implement/scripts/implement_scripts_constants/__init__.py +0 -0
- package/skills/implement/scripts/implement_scripts_constants/notes_constants.py +12 -0
- package/skills/implement/scripts/test_append_note.py +191 -0
- package/skills/pr-converge/pr_converge_skill_constants/__init__.py +0 -0
- package/skills/pr-converge/{config → pr_converge_skill_constants}/constants.py +6 -1
- package/skills/pr-converge/scripts/check_bugbot_ci.py +2 -2
- package/skills/pr-converge/scripts/check_convergence.py +175 -29
- package/skills/pr-converge/scripts/check_pending_reviews.py +2 -2
- package/skills/pr-converge/scripts/fetch_copilot_reviews.py +2 -2
- package/skills/pr-converge/scripts/post_fix_reply.py +2 -2
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/__init__.py +0 -0
- package/skills/pr-converge/scripts/{config → pr_converge_scripts_constants}/pr_converge_constants.py +1 -1
- package/skills/pr-converge/scripts/reflow_skill_md.py +90 -16
- package/skills/pr-converge/scripts/test_check_bugbot_ci.py +1 -1
- package/skills/pr-converge/scripts/test_check_convergence.py +324 -0
- package/skills/pr-converge/scripts/test_reflow_skill_md.py +0 -31
- package/skills/refine/SKILL.md +257 -0
- package/skills/refine/templates/implementation-notes-template.html +56 -0
- package/skills/refine/templates/plan-template.md +60 -0
- package/skills/session-log/SKILL.md +98 -233
- package/_shared/pr-loop/scripts/config/claude_permissions_constants.py +0 -36
- package/hooks/config/pr_description_enforcer_constants.py +0 -19
- package/hooks/config/test_pr_description_enforcer_constants.py +0 -82
- package/skills/bugteam/scripts/config/claude_permissions_common_constants.py +0 -20
- package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +0 -55
- package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +0 -55
- package/skills/pr-converge/scripts/evict_cached_config_modules.py +0 -20
- package/skills/pr-converge/scripts/test_evict_cached_config_modules.py +0 -22
- /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/__init__.py +0 -0
- /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/code_rules_gate_constants.py +0 -0
- /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/fix_hookspath_constants.py +0 -0
- /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/post_audit_thread_constants.py +0 -0
- /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/preflight_constants.py +0 -0
- /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/reviews_disabled_constants.py +0 -0
- /package/hooks/git-hooks/{config.py → git_hooks_constants/__init__.py} +0 -0
- /package/hooks/{config → hooks_constants}/__init__.py +0 -0
- /package/hooks/{config → hooks_constants}/any_type_config.py +0 -0
- /package/hooks/{config → hooks_constants}/banned_identifiers_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/blocking_check_limits.py +0 -0
- /package/hooks/{config → hooks_constants}/bot_mention_comment_blocker_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/convergence_branch_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/doc_gist_auto_publish_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/dynamic_stderr_handler.py +0 -0
- /package/hooks/{config → hooks_constants}/gh_pr_author_swap_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/hardcoded_user_path_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/hook_log_extractor_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/html_companion_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/inline_tuple_string_magic_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/messages.py +0 -0
- /package/hooks/{config → hooks_constants}/path_rewriter_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/pr_converge_bugteam_enforcer_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/session_env_cleanup_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/setup_project_paths_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/state_description_blocker_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/stuttering_check_config.py +0 -0
- /package/hooks/{config → hooks_constants}/stuttering_import_binding_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/sys_path_insert_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/unused_module_import_constants.py +0 -0
- /package/hooks/{config → hooks_constants}/windows_rmtree_blocker_constants.py +0 -0
- /package/{skills/_shared/pr-loop/scripts/config → hooks/lifecycle}/__init__.py +0 -0
- /package/{skills/bugteam/scripts/config → hooks/session}/__init__.py +0 -0
- /package/scripts/{config → dev_env_scripts_constants}/__init__.py +0 -0
- /package/skills/{doc-gist/scripts/config → _shared/pr-loop/scripts/skills_pr_loop_constants}/__init__.py +0 -0
- /package/skills/_shared/pr-loop/scripts/{config → skills_pr_loop_constants}/path_resolver_constants.py +0 -0
- /package/skills/{pr-converge/config → bugteam/scripts/bugteam_scripts_constants}/__init__.py +0 -0
- /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_code_rules_gate_constants.py +0 -0
- /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_fix_hookspath_constants.py +0 -0
- /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_preflight_constants.py +0 -0
- /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/probe_code_rules_enforcer_check_constants.py +0 -0
- /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/reflow_skill_md_constants.py +0 -0
- /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/windows_safe_rmtree_constants.py +0 -0
- /package/skills/{pr-converge/scripts/config → doc-gist/scripts/doc_gist_scripts_constants}/__init__.py +0 -0
- /package/skills/doc-gist/scripts/{config → doc_gist_scripts_constants}/gist_upload_constants.py +0 -0
- /package/skills/pr-converge/scripts/{config → pr_converge_scripts_constants}/reflow_skill_md_constants.py +0 -0
|
@@ -16,7 +16,7 @@ import os
|
|
|
16
16
|
import sys
|
|
17
17
|
import time
|
|
18
18
|
|
|
19
|
-
from
|
|
19
|
+
from dev_env_scripts_constants.timing import DEFAULT_AGE_SECONDS, DEFAULT_POLL_INTERVAL
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def _positive_int(raw_argument: str) -> int:
|
|
@@ -42,6 +42,15 @@ def sweep(root: str, min_age_seconds: int) -> list[str]:
|
|
|
42
42
|
Walks bottom-up so nested empty directories are cleaned from the leaves
|
|
43
43
|
inward. Relies on os.rmdir to fail harmlessly for non-empty directories
|
|
44
44
|
instead of checking snapshotted subdirectory lists.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
root: Root directory to walk; directories below the root are
|
|
48
|
+
candidates for removal.
|
|
49
|
+
min_age_seconds: Minimum age in seconds for a directory to qualify
|
|
50
|
+
for removal.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Sorted list of directory paths that were removed during the sweep.
|
|
45
54
|
"""
|
|
46
55
|
|
|
47
56
|
all_removed: list[str] = []
|
|
@@ -22,8 +22,8 @@ for each_sys_path_entry in (
|
|
|
22
22
|
|
|
23
23
|
import setup_project_paths as setup
|
|
24
24
|
import untracked_repo_detector as detector_module
|
|
25
|
-
from
|
|
26
|
-
from
|
|
25
|
+
from hooks_constants.project_paths_reader import registry_file_path
|
|
26
|
+
from hooks_constants.setup_project_paths_constants import (
|
|
27
27
|
ABORTED_NOTHING_WRITTEN_MESSAGE,
|
|
28
28
|
CONFIRMATION_PROMPT_TEXT,
|
|
29
29
|
ES_EXE_FOLDERS_ONLY_QUERY_ARGUMENTS,
|
|
@@ -15,10 +15,6 @@ _SCRIPTS_DIR = Path(os.path.abspath(__file__)).parent
|
|
|
15
15
|
if str(_SCRIPTS_DIR) not in sys.path:
|
|
16
16
|
sys.path.insert(0, str(_SCRIPTS_DIR))
|
|
17
17
|
|
|
18
|
-
for _cached in list(sys.modules):
|
|
19
|
-
if _cached == "config" or _cached.startswith("config."):
|
|
20
|
-
del sys.modules[_cached]
|
|
21
|
-
|
|
22
18
|
from sweep_empty_dirs import _build_parser, _positive_int, sweep # noqa: E402
|
|
23
19
|
|
|
24
20
|
_OLD_TIMESTAMP = time.time() - 300
|
|
@@ -53,7 +49,7 @@ def test_positive_int_rejects_non_integer() -> None:
|
|
|
53
49
|
|
|
54
50
|
|
|
55
51
|
def test_build_parser_sets_age_default_from_timing_config() -> None:
|
|
56
|
-
"""_build_parser uses DEFAULT_AGE_SECONDS from
|
|
52
|
+
"""_build_parser uses DEFAULT_AGE_SECONDS from dev_env_scripts_constants.timing as --age default."""
|
|
57
53
|
parser = _build_parser()
|
|
58
54
|
default_age = parser.get_default("age")
|
|
59
55
|
assert isinstance(default_age, int)
|
|
@@ -61,7 +57,7 @@ def test_build_parser_sets_age_default_from_timing_config() -> None:
|
|
|
61
57
|
|
|
62
58
|
|
|
63
59
|
def test_build_parser_sets_interval_default_from_timing_config() -> None:
|
|
64
|
-
"""_build_parser uses DEFAULT_POLL_INTERVAL from
|
|
60
|
+
"""_build_parser uses DEFAULT_POLL_INTERVAL from dev_env_scripts_constants.timing as --interval default."""
|
|
65
61
|
parser = _build_parser()
|
|
66
62
|
default_interval = parser.get_default("interval")
|
|
67
63
|
assert isinstance(default_interval, int)
|
|
@@ -9,7 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
import tempfile
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
-
from
|
|
12
|
+
from skills_pr_loop_constants.path_resolver_constants import (
|
|
13
13
|
DIFF_PATCH_TEMPLATE,
|
|
14
14
|
FIX_OUTCOME_XML_TEMPLATE,
|
|
15
15
|
MULTI_PR_SLUG_TEMPLATE,
|
|
@@ -19,7 +19,7 @@ if str(_self_dir) not in sys.path:
|
|
|
19
19
|
sys.path.insert(0, str(_self_dir))
|
|
20
20
|
|
|
21
21
|
from _xml_utils import emit_pretty_xml
|
|
22
|
-
from
|
|
22
|
+
from skills_pr_loop_constants.path_resolver_constants import (
|
|
23
23
|
ALL_AUDIT_CATEGORY_ENTRIES,
|
|
24
24
|
ALL_AUDIT_CONSTRAINT_TEXTS,
|
|
25
25
|
)
|
|
@@ -21,7 +21,7 @@ if str(_self_dir) not in sys.path:
|
|
|
21
21
|
|
|
22
22
|
from _cli_utils import require_file
|
|
23
23
|
from _xml_utils import emit_pretty_xml
|
|
24
|
-
from
|
|
24
|
+
from skills_pr_loop_constants.path_resolver_constants import (
|
|
25
25
|
ALL_FIX_CONSTRAINT_TEXTS,
|
|
26
26
|
ALL_FIX_EXECUTION_STEPS,
|
|
27
27
|
)
|
|
@@ -20,7 +20,7 @@ from _path_resolver import (
|
|
|
20
20
|
per_pr_workspace,
|
|
21
21
|
resolve_run_temp_dir,
|
|
22
22
|
)
|
|
23
|
-
from
|
|
23
|
+
from skills_pr_loop_constants.path_resolver_constants import LOOP_STATE_JSON_INDENT
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def create_loop_state(
|
|
@@ -24,7 +24,7 @@ if str(_self_dir) not in sys.path:
|
|
|
24
24
|
sys.path.insert(0, str(_self_dir))
|
|
25
25
|
|
|
26
26
|
from _path_resolver import per_pr_workspace
|
|
27
|
-
from
|
|
27
|
+
from skills_pr_loop_constants.path_resolver_constants import ALL_PYTHON_ONEXC_VERSION
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
def _remove_readonly_attribute(
|
|
@@ -19,7 +19,7 @@ if str(_self_dir) not in sys.path:
|
|
|
19
19
|
from _cli_utils import require_file
|
|
20
20
|
from _path_resolver import outcome_xml_path
|
|
21
21
|
from _xml_utils import emit_pretty_xml
|
|
22
|
-
from
|
|
22
|
+
from skills_pr_loop_constants.path_resolver_constants import ALL_FINDING_BODY_ELEMENT_KEYS
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def build_audit_xml(
|
|
@@ -70,7 +70,7 @@ def _populate_findings(parent: Element, findings_data: list[dict[str, object]])
|
|
|
70
70
|
|
|
71
71
|
Scalar finding fields become XML attributes on `<finding>`; the
|
|
72
72
|
body fields named in `ALL_FINDING_BODY_ELEMENT_KEYS` (defined in
|
|
73
|
-
`packages/claude-dev-env/skills/_shared/pr-loop/scripts/
|
|
73
|
+
`packages/claude-dev-env/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py`
|
|
74
74
|
and currently `("title", "excerpt", "description")`) become child elements.
|
|
75
75
|
Nested dicts or lists in scalar slots are flattened to string form
|
|
76
76
|
so attribute serialization stays well-defined.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Validate status enum values and write <bugteam_fix> XML at the canonical path.
|
|
2
2
|
|
|
3
3
|
Status enum (canonical source: `ALL_VALID_FIX_STATUSES` in
|
|
4
|
-
`packages/claude-dev-env/skills/_shared/pr-loop/scripts/
|
|
4
|
+
`packages/claude-dev-env/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py`):
|
|
5
5
|
fixed | could_not_address | hook_blocked | unverified_fixed.
|
|
6
6
|
|
|
7
7
|
Each outcome's scalar fields become XML attributes on `<outcome>`; the
|
|
@@ -27,7 +27,7 @@ if str(_self_dir) not in sys.path:
|
|
|
27
27
|
from _cli_utils import require_file
|
|
28
28
|
from _path_resolver import fix_outcome_xml_path
|
|
29
29
|
from _xml_utils import emit_pretty_xml
|
|
30
|
-
from
|
|
30
|
+
from skills_pr_loop_constants.path_resolver_constants import (
|
|
31
31
|
ALL_FIX_OUTCOME_BODY_ELEMENT_KEYS,
|
|
32
32
|
ALL_VALID_FIX_STATUSES,
|
|
33
33
|
)
|
|
@@ -108,7 +108,7 @@ cd into `<worktree_path>` before any git or file operation.
|
|
|
108
108
|
teammate does NOT author the inline-comment body directly:
|
|
109
109
|
`post_audit_thread.py` renders every body from
|
|
110
110
|
`INLINE_COMMENT_BODY_TEMPLATE` (defined in
|
|
111
|
-
[`_shared/pr-loop/scripts/
|
|
111
|
+
[`_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py))
|
|
112
112
|
— the template prepends `**[<severity>] <Skill> audit finding**`
|
|
113
113
|
and renders the suggested-fix block, so a teammate who hand-formats
|
|
114
114
|
a title or footer wastes the work.
|
package/skills/bugteam/SKILL.md
CHANGED
|
@@ -103,7 +103,7 @@ narrative) becomes `description`, and the suffix starting at `Fix:`
|
|
|
103
103
|
When the agent omits the `Fix:` heading on a given finding, write the
|
|
104
104
|
full `failure_mode` text to BOTH `description` and `fix_summary` so the
|
|
105
105
|
script's body template (`INLINE_COMMENT_BODY_TEMPLATE` in
|
|
106
|
-
[`_shared/pr-loop/scripts/
|
|
106
|
+
[`_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py))
|
|
107
107
|
still renders coherently. Set `side="RIGHT"` for every entry. On CLEAN,
|
|
108
108
|
pass an empty array (`[]`) so the script posts an APPROVE review
|
|
109
109
|
(GitHub stores it as `state=APPROVED`) with a "no findings" summary and
|
|
@@ -22,7 +22,7 @@ python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/post_audit_thread.py"
|
|
|
22
22
|
|
|
23
23
|
Capture `<head_sha>` via `git rev-parse HEAD` in the subagent cwd immediately before this call so the review attaches to the commit the audit actually scoped.
|
|
24
24
|
|
|
25
|
-
`--findings-json` points to a JSON file whose root is a list of objects shaped `{path, line, side, severity, description, fix_summary}`. Build it from the merged Shape A findings: finding `file` → `path`. Each finding's `failure_mode` carries the full audit-to-fix handoff text per [`agents/code-quality-agent.md`](../../../agents/code-quality-agent.md); split `failure_mode` at the literal `Fix:` heading so the failure narrative becomes `description` and the suffix beginning at `Fix:` (including the trailing `Validation:` clause) becomes `fix_summary`. When a finding's `failure_mode` omits the `Fix:` heading, write the full text to BOTH `description` and `fix_summary` so the script's body template (`INLINE_COMMENT_BODY_TEMPLATE` in [`packages/claude-dev-env/_shared/pr-loop/scripts/
|
|
25
|
+
`--findings-json` points to a JSON file whose root is a list of objects shaped `{path, line, side, severity, description, fix_summary}`. Build it from the merged Shape A findings: finding `file` → `path`. Each finding's `failure_mode` carries the full audit-to-fix handoff text per [`agents/code-quality-agent.md`](../../../agents/code-quality-agent.md); split `failure_mode` at the literal `Fix:` heading so the failure narrative becomes `description` and the suffix beginning at `Fix:` (including the trailing `Validation:` clause) becomes `fix_summary`. When a finding's `failure_mode` omits the `Fix:` heading, write the full text to BOTH `description` and `fix_summary` so the script's body template (`INLINE_COMMENT_BODY_TEMPLATE` in [`packages/claude-dev-env/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py`](../../../_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py)) renders coherently. Set `side="RIGHT"` for every entry. On CLEAN the list is empty (`[]`); on DIRTY the list carries one entry per finding.
|
|
26
26
|
|
|
27
27
|
The script handles retries internally — 1s / 4s / 16s backoff across four attempts (one initial plus three retries). Exit codes:
|
|
28
28
|
|
package/skills/bugteam/scripts/{_claude_permissions_common.py → _bugteam_permissions_common.py}
RENAMED
|
@@ -12,27 +12,17 @@ import json
|
|
|
12
12
|
import os
|
|
13
13
|
import stat
|
|
14
14
|
import sys
|
|
15
|
+
from collections.abc import Callable
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
from typing import NoReturn
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
each_module_key
|
|
21
|
-
for each_module_key in list(sys.modules)
|
|
22
|
-
if each_module_key == "config" or each_module_key.startswith("config.")
|
|
23
|
-
]:
|
|
24
|
-
_previously_cached_config[each_cached_module_name] = sys.modules.pop(
|
|
25
|
-
each_cached_module_name
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
from config.claude_permissions_common_constants import (
|
|
19
|
+
from bugteam_scripts_constants.claude_permissions_common_constants import (
|
|
20
|
+
ALL_TRUST_ENTRY_PROJECT_PATH_BOUNDARY_QUOTE_CHARACTERS,
|
|
29
21
|
ATOMIC_WRITE_TEMPORARY_SUFFIX,
|
|
30
22
|
DEFAULT_SETTINGS_FILE_MODE,
|
|
31
23
|
TEXT_FILE_ENCODING,
|
|
32
24
|
)
|
|
33
25
|
|
|
34
|
-
sys.modules.update(_previously_cached_config)
|
|
35
|
-
|
|
36
26
|
|
|
37
27
|
def exit_with_error(message: str) -> NoReturn:
|
|
38
28
|
print(f"Error: {message}", file=sys.stderr)
|
|
@@ -105,6 +95,113 @@ def build_permission_rules(
|
|
|
105
95
|
]
|
|
106
96
|
|
|
107
97
|
|
|
98
|
+
def build_agent_config_deny_rule(
|
|
99
|
+
tool_name: str, project_path: str, agent_config_path_pattern: str
|
|
100
|
+
) -> str:
|
|
101
|
+
"""Construct a deny rule for a single agent-config path pattern.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
tool_name: The permission tool name (e.g., "Edit", "Write", "Read").
|
|
105
|
+
project_path: The POSIX-style project root path.
|
|
106
|
+
agent_config_path_pattern: The agent-config path pattern under .claude/.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
The deny rule string Claude Code matches against tool invocations.
|
|
110
|
+
"""
|
|
111
|
+
return f"{tool_name}({project_path}/.claude/{agent_config_path_pattern})"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def build_agent_config_deny_rules(
|
|
115
|
+
project_path: str,
|
|
116
|
+
all_permission_allow_tools: tuple[str, ...],
|
|
117
|
+
all_agent_config_path_patterns: tuple[str, ...],
|
|
118
|
+
) -> list[str]:
|
|
119
|
+
"""Construct deny rules covering every tool and pattern pair.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
project_path: The POSIX-style project root path.
|
|
123
|
+
all_permission_allow_tools: Tool names to build deny rules for.
|
|
124
|
+
all_agent_config_path_patterns: Agent-config path patterns to deny under .claude/.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
List of deny rule strings, one per tool/pattern combination.
|
|
128
|
+
"""
|
|
129
|
+
return [
|
|
130
|
+
build_agent_config_deny_rule(each_tool, project_path, each_pattern)
|
|
131
|
+
for each_tool in all_permission_allow_tools
|
|
132
|
+
for each_pattern in all_agent_config_path_patterns
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _is_project_path_token_at_word_boundary(
|
|
137
|
+
body_after_prefix: str, token_position: int
|
|
138
|
+
) -> bool:
|
|
139
|
+
if token_position == 0:
|
|
140
|
+
return True
|
|
141
|
+
preceding_character = body_after_prefix[token_position - 1]
|
|
142
|
+
if preceding_character.isspace():
|
|
143
|
+
return True
|
|
144
|
+
return preceding_character in ALL_TRUST_ENTRY_PROJECT_PATH_BOUNDARY_QUOTE_CHARACTERS
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def is_trust_entry_for_project(
|
|
148
|
+
candidate_entry: object, project_path: str, prefix: str
|
|
149
|
+
) -> bool:
|
|
150
|
+
"""Detect whether an autoMode.environment entry is a trust entry for the project.
|
|
151
|
+
|
|
152
|
+
The predicate matches any string entry whose prefix matches the trust-entry
|
|
153
|
+
marker and that contains the project's .claude/** path token anchored on a
|
|
154
|
+
non-path boundary (the start of the body after the prefix, a whitespace
|
|
155
|
+
character, or a quote character). The boundary anchor prevents
|
|
156
|
+
cross-project false positives where the current project's path is a path
|
|
157
|
+
suffix of an unrelated entry's path. The exact wording after the prefix is
|
|
158
|
+
allowed to vary between template revisions.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
candidate_entry: The autoMode.environment list value to inspect.
|
|
162
|
+
project_path: The POSIX-style project root path.
|
|
163
|
+
prefix: The literal prefix that marks a trust entry.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
True when the entry is a prior trust entry for this project.
|
|
167
|
+
"""
|
|
168
|
+
if not isinstance(candidate_entry, str):
|
|
169
|
+
return False
|
|
170
|
+
if not candidate_entry.startswith(prefix):
|
|
171
|
+
return False
|
|
172
|
+
project_path_token = f"{project_path}/.claude/**"
|
|
173
|
+
body_after_prefix = candidate_entry[len(prefix):]
|
|
174
|
+
token_position = body_after_prefix.find(project_path_token)
|
|
175
|
+
while token_position != -1:
|
|
176
|
+
if _is_project_path_token_at_word_boundary(body_after_prefix, token_position):
|
|
177
|
+
return True
|
|
178
|
+
next_search_start = token_position + 1
|
|
179
|
+
token_position = body_after_prefix.find(project_path_token, next_search_start)
|
|
180
|
+
return False
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def remove_matching_entries_from_list(
|
|
184
|
+
all_target_list: list[object],
|
|
185
|
+
match_predicate: Callable[[object], bool],
|
|
186
|
+
) -> int:
|
|
187
|
+
"""Remove every entry from a list that satisfies the predicate.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
all_target_list: The list to filter in place.
|
|
191
|
+
match_predicate: Function returning True for entries to remove.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Number of entries removed.
|
|
195
|
+
"""
|
|
196
|
+
original_length = len(all_target_list)
|
|
197
|
+
all_target_list[:] = [
|
|
198
|
+
each_value
|
|
199
|
+
for each_value in all_target_list
|
|
200
|
+
if not match_predicate(each_value)
|
|
201
|
+
]
|
|
202
|
+
return original_length - len(all_target_list)
|
|
203
|
+
|
|
204
|
+
|
|
108
205
|
def load_settings(settings_path: Path) -> dict[str, object]:
|
|
109
206
|
"""Read and parse a JSON settings file from disk.
|
|
110
207
|
|
|
@@ -11,17 +11,7 @@ from pathlib import Path
|
|
|
11
11
|
|
|
12
12
|
ValidateContentCallable = Callable[..., list[str]]
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
for each_cached_module_name in [
|
|
16
|
-
each_module_key
|
|
17
|
-
for each_module_key in list(sys.modules)
|
|
18
|
-
if each_module_key == "config" or each_module_key.startswith("config.")
|
|
19
|
-
]:
|
|
20
|
-
_previously_cached_config[each_cached_module_name] = sys.modules.pop(
|
|
21
|
-
each_cached_module_name
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
from config.bugteam_code_rules_gate_constants import (
|
|
14
|
+
from bugteam_scripts_constants.bugteam_code_rules_gate_constants import (
|
|
25
15
|
ALL_CODE_FILE_EXTENSIONS,
|
|
26
16
|
ALL_COLUMN_MAGIC_FALSE_VALUES,
|
|
27
17
|
ALL_GIT_DIFF_CACHED_ARGS,
|
|
@@ -34,8 +24,6 @@ from config.bugteam_code_rules_gate_constants import (
|
|
|
34
24
|
VIOLATION_LINE_RAW_PATTERN,
|
|
35
25
|
)
|
|
36
26
|
|
|
37
|
-
sys.modules.update(_previously_cached_config)
|
|
38
|
-
|
|
39
27
|
|
|
40
28
|
def hunk_header_pattern() -> re.Pattern[str]:
|
|
41
29
|
return re.compile(HUNK_HEADER_RAW_PATTERN)
|
|
@@ -5,22 +5,7 @@ import subprocess
|
|
|
5
5
|
import sys
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
try:
|
|
10
|
-
sys.path.remove(parent_directory)
|
|
11
|
-
except ValueError:
|
|
12
|
-
pass
|
|
13
|
-
if parent_directory not in sys.path:
|
|
14
|
-
sys.path.insert(0, parent_directory)
|
|
15
|
-
|
|
16
|
-
for each_cached_module_name in [
|
|
17
|
-
each_module_key
|
|
18
|
-
for each_module_key in list(sys.modules)
|
|
19
|
-
if each_module_key == "config" or each_module_key.startswith("config.")
|
|
20
|
-
]:
|
|
21
|
-
sys.modules.pop(each_cached_module_name, None)
|
|
22
|
-
|
|
23
|
-
from config.bugteam_fix_hookspath_constants import (
|
|
8
|
+
from bugteam_scripts_constants.bugteam_fix_hookspath_constants import (
|
|
24
9
|
ALL_CANONICAL_HOOKS_DIRECTORY_COMPONENTS,
|
|
25
10
|
ALL_GLOBAL_HOOKS_PATH_ARGUMENTS,
|
|
26
11
|
ALL_HOME_ENV_VAR_NAMES,
|
|
@@ -6,19 +6,13 @@ import subprocess
|
|
|
6
6
|
import sys
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
|
-
for each_cached_module_name in [
|
|
10
|
-
each_module_key
|
|
11
|
-
for each_module_key in list(sys.modules)
|
|
12
|
-
if each_module_key == "config" or each_module_key.startswith("config.")
|
|
13
|
-
]:
|
|
14
|
-
sys.modules.pop(each_cached_module_name, None)
|
|
15
9
|
_bugteam_scripts_directory = str(Path(__file__).absolute().parent)
|
|
16
10
|
while _bugteam_scripts_directory in sys.path:
|
|
17
11
|
sys.path.remove(_bugteam_scripts_directory)
|
|
18
12
|
if _bugteam_scripts_directory not in sys.path:
|
|
19
13
|
sys.path.insert(0, _bugteam_scripts_directory)
|
|
20
14
|
|
|
21
|
-
from
|
|
15
|
+
from bugteam_scripts_constants.bugteam_preflight_constants import (
|
|
22
16
|
ALL_DISCOVERY_IGNORE_DIRECTORIES,
|
|
23
17
|
ALL_GIT_CONFIG_HOOKS_PATH_ARGUMENTS,
|
|
24
18
|
ALL_PRE_COMMIT_ARGUMENTS,
|
|
@@ -35,12 +29,6 @@ from config.bugteam_preflight_constants import (
|
|
|
35
29
|
PYTEST_INI_FILENAME,
|
|
36
30
|
)
|
|
37
31
|
|
|
38
|
-
for each_cached_module_name in [
|
|
39
|
-
each_module_key
|
|
40
|
-
for each_module_key in list(sys.modules)
|
|
41
|
-
if each_module_key == "config" or each_module_key.startswith("config.")
|
|
42
|
-
]:
|
|
43
|
-
sys.modules.pop(each_cached_module_name, None)
|
|
44
32
|
_shared_pr_loop_scripts_directory = (
|
|
45
33
|
Path(__file__).absolute().parent
|
|
46
34
|
/ ".." / ".." / ".." / "_shared" / "pr-loop" / "scripts"
|
package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Configuration constants for claude_permissions_common shared helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
TEXT_FILE_ENCODING: str = "utf-8"
|
|
6
|
+
ALL_PERMISSION_ALLOW_TOOLS: tuple[str, ...] = ("Edit", "Write", "Read")
|
|
7
|
+
ALL_AGENT_CONFIG_DENY_TOOLS: tuple[str, ...] = ("Edit", "Write", "Read", "Glob")
|
|
8
|
+
ALL_AGENT_CONFIG_PATH_PATTERNS: tuple[str, ...] = (
|
|
9
|
+
"settings*.json",
|
|
10
|
+
"hooks/**",
|
|
11
|
+
"commands/**",
|
|
12
|
+
"agents/**",
|
|
13
|
+
"skills/**",
|
|
14
|
+
"mcp.json",
|
|
15
|
+
"CLAUDE.md",
|
|
16
|
+
)
|
|
17
|
+
AUTO_MODE_ENVIRONMENT_ENTRY_PREFIX: str = "Trusted local workspace:"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _describe_agent_config_pattern_for_humans(agent_config_path_pattern: str) -> str:
|
|
21
|
+
glob_suffix_under_directory = "/**"
|
|
22
|
+
file_name_for_special_phrasing = "mcp.json"
|
|
23
|
+
if agent_config_path_pattern.endswith(glob_suffix_under_directory):
|
|
24
|
+
directory_name = agent_config_path_pattern[
|
|
25
|
+
: -len(glob_suffix_under_directory)
|
|
26
|
+
]
|
|
27
|
+
return f"anything under {directory_name}/"
|
|
28
|
+
if agent_config_path_pattern == file_name_for_special_phrasing:
|
|
29
|
+
return f"the {file_name_for_special_phrasing} file"
|
|
30
|
+
return agent_config_path_pattern
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _build_agent_config_pattern_phrase(
|
|
34
|
+
all_agent_config_path_patterns: tuple[str, ...],
|
|
35
|
+
) -> str:
|
|
36
|
+
all_described_patterns: list[str] = [
|
|
37
|
+
_describe_agent_config_pattern_for_humans(each_pattern)
|
|
38
|
+
for each_pattern in all_agent_config_path_patterns
|
|
39
|
+
]
|
|
40
|
+
if len(all_described_patterns) <= 1:
|
|
41
|
+
return ", ".join(all_described_patterns)
|
|
42
|
+
leading_phrase_parts = ", ".join(all_described_patterns[:-1])
|
|
43
|
+
final_phrase_part = all_described_patterns[-1]
|
|
44
|
+
return f"{leading_phrase_parts}, and {final_phrase_part}"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
_AGENT_CONFIG_PATTERN_PHRASE: str = _build_agent_config_pattern_phrase(
|
|
48
|
+
ALL_AGENT_CONFIG_PATH_PATTERNS
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
AUTO_MODE_ENVIRONMENT_ENTRY_TEMPLATE: str = (
|
|
52
|
+
f"Trusted local workspace: Files under {{project_path}}/.claude/** inherit "
|
|
53
|
+
f"the workspace's trust for Edit, Write, Read, and Glob operations EXCEPT "
|
|
54
|
+
f"for agent-config files: {_AGENT_CONFIG_PATTERN_PHRASE}. Edits to those "
|
|
55
|
+
f"agent-config files always require explicit per-edit user approval."
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
ALL_TRUST_ENTRY_PROJECT_PATH_BOUNDARY_QUOTE_CHARACTERS: tuple[str, ...] = ('"', "'")
|
|
59
|
+
ATOMIC_WRITE_TEMPORARY_SUFFIX: str = ".tmp"
|
|
60
|
+
GIT_DIRECTORY_MARKER: str = ".git"
|
|
61
|
+
CLAUDE_DIRECTORY_MARKER: str = ".claude"
|
|
62
|
+
CLAUDE_USER_SETTINGS_FILENAME: str = "settings.json"
|
|
63
|
+
DEFAULT_SETTINGS_FILE_MODE: int = 0o600
|
|
64
|
+
SETTINGS_PERMISSIONS_KEY: str = "permissions"
|
|
65
|
+
SETTINGS_ALLOW_KEY: str = "allow"
|
|
66
|
+
SETTINGS_DENY_KEY: str = "deny"
|
|
67
|
+
SETTINGS_ADDITIONAL_DIRECTORIES_KEY: str = "additionalDirectories"
|
|
68
|
+
SETTINGS_AUTO_MODE_KEY: str = "autoMode"
|
|
69
|
+
SETTINGS_ENVIRONMENT_KEY: str = "environment"
|