claude-dev-env 2.15.0 → 2.15.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.
Files changed (28) hide show
  1. package/_shared/advisor/scripts/tier_model_ids.py +6 -2
  2. package/bin/install.mjs +35 -32
  3. package/bin/install.test.mjs +42 -8
  4. package/package.json +2 -2
  5. package/scripts/AGENTS.md +0 -7
  6. package/scripts/claude_chain_runner.py +49 -2
  7. package/scripts/invoke_code_review.py +48 -51
  8. package/scripts/resolve_worker_spawn.py +42 -47
  9. package/scripts/test_claude_chain_runner.py +28 -0
  10. package/scripts/test_dispatcher_profile_import.py +184 -0
  11. package/scripts/test_resolve_worker_spawn.py +119 -1
  12. package/scripts/test_validate_instruction_pairs.py +30 -0
  13. package/scripts/profile-isolation-launchers/config/mcp-bundles.json +0 -25
  14. package/scripts/profile-isolation-launchers/config/profile-isolation-constants.mjs +0 -60
  15. package/scripts/profile-isolation-launchers/config/profiles.manifest.json +0 -54
  16. package/scripts/profile-isolation-launchers/config/shared-allowlist.json +0 -64
  17. package/scripts/profile-isolation-launchers/launcher-runtime.mjs +0 -180
  18. package/scripts/profile-isolation-launchers/lib/profile-manifest.mjs +0 -288
  19. package/scripts/profile-isolation-launchers/mcp-bundles.mjs +0 -275
  20. package/scripts/profile-isolation-launchers/profile-isolation-contract.test.mjs +0 -221
  21. package/scripts/profile-isolation-launchers/tests/launcher-runtime.test.mjs +0 -108
  22. package/scripts/profile-isolation-launchers/tests/mcp-bundles.test.mjs +0 -147
  23. package/scripts/profile-isolation-launchers/tests/shortcut-contract.test.ps1 +0 -102
  24. package/scripts/profile-isolation-launchers/tests/version-compatibility.test.mjs +0 -210
  25. package/scripts/profile-isolation-launchers/version-compatibility.mjs +0 -299
  26. package/scripts/profile-isolation-launchers/windows/shortcut-inventory.ps1 +0 -127
  27. package/scripts/profile-isolation-launchers/windows/shortcut-manifest.json +0 -51
  28. package/scripts/profile-isolation-launchers/windows/shortcut-reconcile.ps1 +0 -77
@@ -0,0 +1,184 @@
1
+ """Exercise the installed dispatcher layout in isolated profile trees."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ import pytest
12
+
13
+ _DISPATCHER_NAMES = ("resolve_worker_spawn.py", "invoke_code_review.py")
14
+ _SHARED_DIRECTORY_NAMES = ("advisor", "process-tree")
15
+
16
+
17
+ def _stage_profile_tree(
18
+ source_package_directory: Path, target_profile_directory: Path
19
+ ) -> Path:
20
+ source_scripts_directory = source_package_directory / "scripts"
21
+ target_scripts_directory = target_profile_directory / "scripts"
22
+ shutil.copytree(source_scripts_directory, target_scripts_directory)
23
+ for each_shared_name in _SHARED_DIRECTORY_NAMES:
24
+ source_shared_directory = (
25
+ source_package_directory / "_shared" / each_shared_name
26
+ )
27
+ target_shared_directory = (
28
+ target_profile_directory / "_shared" / each_shared_name
29
+ )
30
+ shutil.copytree(source_shared_directory, target_shared_directory)
31
+ return target_scripts_directory
32
+
33
+
34
+ def _stage_shadow_import_root(
35
+ target_profile_directory: Path, dispatcher_module_name: str
36
+ ) -> Path:
37
+ shadow_import_root = (
38
+ target_profile_directory / f"shadow-import-root-{dispatcher_module_name}"
39
+ )
40
+ shadow_import_root.mkdir()
41
+ (shadow_import_root / "tier_model_ids.py").write_text(
42
+ "raise RuntimeError('shadow tier_model_ids imported')\n",
43
+ encoding="utf-8",
44
+ )
45
+ (shadow_import_root / "claude_chain_runner.py").write_text(
46
+ "raise RuntimeError('shadow claude_chain_runner imported')\n",
47
+ encoding="utf-8",
48
+ )
49
+ shadow_constants_root = shadow_import_root / "advisor_scripts_constants"
50
+ shadow_constants_root.mkdir()
51
+ (shadow_constants_root / "__init__.py").write_text(
52
+ "raise RuntimeError('shadow advisor constants imported')\n",
53
+ encoding="utf-8",
54
+ )
55
+ shadow_scripts_constants_root = shadow_import_root / "dev_env_scripts_constants"
56
+ shadow_scripts_constants_root.mkdir()
57
+ (shadow_scripts_constants_root / "__init__.py").write_text(
58
+ "raise RuntimeError('shadow dev-env constants imported')\n",
59
+ encoding="utf-8",
60
+ )
61
+ return shadow_import_root
62
+
63
+
64
+ @pytest.fixture(scope="module")
65
+ def installed_dispatcher_scripts(
66
+ tmp_path_factory: pytest.TempPathFactory,
67
+ ) -> Path:
68
+ """Stage one installed profile for both dispatcher import checks."""
69
+ source_package_directory = Path(__file__).resolve().parent.parent
70
+ target_profile_directory = tmp_path_factory.mktemp("dispatcher_profile") / ".claude"
71
+ return _stage_profile_tree(source_package_directory, target_profile_directory)
72
+
73
+
74
+ @pytest.mark.parametrize("dispatcher_name", _DISPATCHER_NAMES)
75
+ def test_installed_dispatcher_help_imports_advisor_constants(
76
+ dispatcher_name: str, installed_dispatcher_scripts: Path
77
+ ) -> None:
78
+ """Each deployed dispatcher imports and serves help from an isolated tree."""
79
+ target_scripts_directory = installed_dispatcher_scripts
80
+ target_profile_directory = target_scripts_directory.parent
81
+
82
+ completed_process = subprocess.run(
83
+ [
84
+ sys.executable,
85
+ "-S",
86
+ "-E",
87
+ str(target_scripts_directory / dispatcher_name),
88
+ "--help",
89
+ ],
90
+ cwd=target_profile_directory,
91
+ capture_output=True,
92
+ text=True,
93
+ check=False,
94
+ )
95
+
96
+ assert completed_process.returncode == 0
97
+ assert completed_process.stderr == ""
98
+ assert "usage:" in completed_process.stdout
99
+
100
+
101
+ @pytest.mark.parametrize("dispatcher_name", _DISPATCHER_NAMES)
102
+ def test_imported_dispatcher_promotes_all_profile_owned_roots(
103
+ dispatcher_name: str, installed_dispatcher_scripts: Path
104
+ ) -> None:
105
+ """Fresh imported-module loading selects every installed profile root."""
106
+ dispatcher_module_name = dispatcher_name.rsplit(".", maxsplit=1)[0]
107
+ target_profile_directory = installed_dispatcher_scripts.parent
108
+ shadow_import_root = _stage_shadow_import_root(
109
+ target_profile_directory, dispatcher_module_name
110
+ )
111
+ advisor_scripts_root = target_profile_directory / "_shared" / "advisor" / "scripts"
112
+ advisor_config_root = advisor_scripts_root / "config"
113
+ process_tree_scripts_root = (
114
+ target_profile_directory / "_shared" / "process-tree" / "scripts"
115
+ )
116
+ process_tree_config_root = process_tree_scripts_root / "config"
117
+ all_expected_roots = [
118
+ str(advisor_config_root),
119
+ str(advisor_scripts_root),
120
+ str(installed_dispatcher_scripts),
121
+ str(shadow_import_root),
122
+ ]
123
+ if dispatcher_module_name == "resolve_worker_spawn":
124
+ all_expected_roots = [
125
+ str(process_tree_config_root),
126
+ str(process_tree_scripts_root),
127
+ *all_expected_roots,
128
+ ]
129
+ child_code = "\n".join(
130
+ (
131
+ "import importlib",
132
+ "import json",
133
+ "import sys",
134
+ "from pathlib import Path",
135
+ f"dispatcher_module_name = {dispatcher_module_name!r}",
136
+ "shadow_import_root, scripts_root, advisor_scripts_root, advisor_config_root = (",
137
+ f" {str(shadow_import_root)!r},",
138
+ f" {str(installed_dispatcher_scripts)!r},",
139
+ f" {str(advisor_scripts_root)!r},",
140
+ f" {str(advisor_config_root)!r},",
141
+ ")",
142
+ "sys.path[:0] = [",
143
+ " shadow_import_root,",
144
+ " scripts_root,",
145
+ " advisor_scripts_root,",
146
+ " advisor_config_root,",
147
+ "]",
148
+ "assert all(each_name not in sys.modules for each_name in (",
149
+ " dispatcher_module_name,",
150
+ " 'tier_model_ids',",
151
+ " 'advisor_scripts_constants',",
152
+ "))",
153
+ "dispatcher = importlib.import_module(dispatcher_module_name)",
154
+ "tier_model_ids = importlib.import_module('tier_model_ids')",
155
+ "advisor_scripts_constants = importlib.import_module('advisor_scripts_constants')",
156
+ "print(json.dumps({",
157
+ " 'dispatcher': str(Path(dispatcher.__file__).resolve()),",
158
+ " 'tier_model_ids': str(Path(tier_model_ids.__file__).resolve()),",
159
+ " 'advisor_scripts_constants': str(Path(advisor_scripts_constants.__file__).resolve()),",
160
+ " 'roots': sys.path[:6],",
161
+ "}))",
162
+ )
163
+ )
164
+ completed_process = subprocess.run(
165
+ [sys.executable, "-S", "-E", "-c", child_code],
166
+ cwd=target_profile_directory,
167
+ capture_output=True,
168
+ text=True,
169
+ check=False,
170
+ )
171
+
172
+ assert completed_process.returncode == 0, completed_process.stderr
173
+ assert completed_process.stderr == ""
174
+ all_import_results = json.loads(completed_process.stdout)
175
+ assert all_import_results["dispatcher"] == str(
176
+ installed_dispatcher_scripts / dispatcher_name
177
+ )
178
+ assert all_import_results["tier_model_ids"] == str(
179
+ advisor_scripts_root / "tier_model_ids.py"
180
+ )
181
+ assert all_import_results["advisor_scripts_constants"] == str(
182
+ advisor_config_root / "advisor_scripts_constants" / "__init__.py"
183
+ )
184
+ assert all_import_results["roots"][: len(all_expected_roots)] == all_expected_roots
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import io
5
6
  import json
6
7
  import subprocess
7
8
  import sys
@@ -9,6 +10,7 @@ import threading
9
10
  from collections.abc import Sequence
10
11
  from dataclasses import dataclass, field
11
12
  from pathlib import Path
13
+ from typing import Self
12
14
 
13
15
  import pytest
14
16
 
@@ -17,6 +19,7 @@ if str(_SCRIPTS_DIR) not in sys.path:
17
19
  sys.path.insert(0, str(_SCRIPTS_DIR))
18
20
 
19
21
  import claude_chain_runner as chain_runner # noqa: E402
22
+ import invoke_code_review as invoker
20
23
  import resolve_worker_spawn as dispatcher # noqa: E402
21
24
  from claude_chain_runner import ( # noqa: E402
22
25
  ChainAttempt,
@@ -87,6 +90,7 @@ FIXTURE_ROLE = "code-quality-agent"
87
90
  MIN_WORKER_TIMEOUT_SECONDS_CONSTANT_NAME = "MIN_WORKER_TIMEOUT_SECONDS"
88
91
  LARGE_PROMPT_CHARACTER_COUNT = 40000
89
92
  WINDOWS_SAFE_ARGV_ELEMENT_CEILING = 8192
93
+ LOCK_WAIT_TIMEOUT_SECONDS = 1
90
94
  EXPECTED_PRIMARY_AGENT_FOR_DEFAULT_ROLE = Path(
91
95
  ALL_AGENT_FILENAMES_BY_ROLE[DEFAULT_ROLE][0]
92
96
  ).stem
@@ -1085,7 +1089,7 @@ def test_headless_chain_runner_lock_serializes_distinct_cwds(
1085
1089
  claude_outcome=_claude_served(),
1086
1090
  host_profile=HOST_PROFILE_THIRD_PARTY,
1087
1091
  )
1088
- all_errors: list[BaseException] = []
1092
+ all_errors: list[Exception] = []
1089
1093
  barrier = threading.Barrier(2)
1090
1094
 
1091
1095
  def _run_with_working_directory(working_directory: Path) -> None:
@@ -1122,6 +1126,120 @@ def test_headless_chain_runner_lock_serializes_distinct_cwds(
1122
1126
  assert chain_runner.chain_subprocess_runner is not None
1123
1127
 
1124
1128
 
1129
+ def test_shared_chain_runner_lock_serializes_cross_dispatcher_cwds(
1130
+ monkeypatch: pytest.MonkeyPatch, tmp_path: Path
1131
+ ) -> None:
1132
+ first_working_directory = tmp_path / "project-a"
1133
+ second_working_directory = tmp_path / "project-b"
1134
+ first_working_directory.mkdir()
1135
+ second_working_directory.mkdir()
1136
+ observed_working_directories: list[Path] = []
1137
+ all_errors: list[BaseException] = []
1138
+
1139
+ class CoordinatedLock:
1140
+ def __init__(self) -> None:
1141
+ self._lock = threading.Lock()
1142
+ self.first_acquired = threading.Event()
1143
+ self.second_attempted = threading.Event()
1144
+ self.enter_count = 0
1145
+
1146
+ def __enter__(self) -> Self:
1147
+ self.enter_count += 1
1148
+ if self.enter_count == 1:
1149
+ self.first_acquired.set()
1150
+ elif self.enter_count == 2:
1151
+ self.second_attempted.set()
1152
+ self._lock.acquire()
1153
+ return self
1154
+
1155
+ def __exit__(self, *all_positionals: object) -> None:
1156
+ del all_positionals
1157
+ self._lock.release()
1158
+
1159
+ coordinated_lock = CoordinatedLock()
1160
+
1161
+ def tracking_subprocess_runner(
1162
+ all_invocation_tokens: Sequence[str],
1163
+ *all_positionals: object,
1164
+ **all_keywords: object,
1165
+ ) -> subprocess.CompletedProcess[str]:
1166
+ del all_invocation_tokens, all_positionals
1167
+ observed_working_directories.append(Path(str(all_keywords["cwd"])))
1168
+ return subprocess.CompletedProcess(
1169
+ args=["claude"], returncode=0, stdout="{}", stderr=""
1170
+ )
1171
+
1172
+ def run_review_runner(
1173
+ all_claude_arguments: list[str], *, timeout_seconds: int
1174
+ ) -> ChainInvocationOutcome:
1175
+ del all_claude_arguments, timeout_seconds
1176
+ if not coordinated_lock.second_attempted.wait(
1177
+ timeout=LOCK_WAIT_TIMEOUT_SECONDS
1178
+ ):
1179
+ all_errors.append(AssertionError("shared lock was never contended"))
1180
+ return _claude_served()
1181
+ chain_runner.chain_subprocess_runner(
1182
+ ["claude"], capture_output=True, text=True, timeout=1, check=False
1183
+ )
1184
+ return _claude_served()
1185
+
1186
+ def run_spawn_runner(
1187
+ all_claude_arguments: list[str], *, timeout_seconds: int
1188
+ ) -> ChainInvocationOutcome:
1189
+ del all_claude_arguments, timeout_seconds
1190
+ chain_runner.chain_subprocess_runner(
1191
+ ["claude"], capture_output=True, text=True, timeout=1, check=False
1192
+ )
1193
+ return _claude_served()
1194
+
1195
+ monkeypatch.setattr(
1196
+ chain_runner, "chain_subprocess_runner", tracking_subprocess_runner
1197
+ )
1198
+ monkeypatch.setattr(
1199
+ chain_runner, "chain_subprocess_runner_lock", lambda: coordinated_lock,
1200
+ raising=False,
1201
+ )
1202
+ monkeypatch.setattr(invoker, "review_claude_runner", run_review_runner)
1203
+ monkeypatch.setattr(dispatcher, "spawn_claude_runner", run_spawn_runner)
1204
+
1205
+ def run_review() -> None:
1206
+ try:
1207
+ invoker._run_claude_with_empty_stdin(
1208
+ ["-p", "review"],
1209
+ timeout_seconds=1,
1210
+ working_directory=first_working_directory,
1211
+ )
1212
+ except Exception as raised_error: # noqa: BLE001
1213
+ all_errors.append(raised_error)
1214
+
1215
+ def run_spawn() -> None:
1216
+ try:
1217
+ dispatcher._run_claude_with_headless_overrides(
1218
+ ["-p", "spawn"],
1219
+ timeout_seconds=1,
1220
+ working_directory=second_working_directory,
1221
+ prompt_stdin=io.StringIO(FIXTURE_PROMPT_TEXT),
1222
+ )
1223
+ except Exception as raised_error: # noqa: BLE001
1224
+ all_errors.append(raised_error)
1225
+
1226
+ review_thread = threading.Thread(target=run_review)
1227
+ spawn_thread = threading.Thread(target=run_spawn)
1228
+ review_thread.start()
1229
+ coordinated_lock.first_acquired.wait(timeout=LOCK_WAIT_TIMEOUT_SECONDS)
1230
+ spawn_thread.start()
1231
+ review_thread.join(timeout=10)
1232
+ spawn_thread.join(timeout=10)
1233
+
1234
+ assert all_errors == []
1235
+ assert coordinated_lock.enter_count == 2
1236
+ assert observed_working_directories == [
1237
+ first_working_directory,
1238
+ second_working_directory,
1239
+ ]
1240
+ assert chain_runner.chain_subprocess_runner is tracking_subprocess_runner
1241
+
1242
+
1125
1243
  def test_usage_limit_fallover_delivers_full_prompt_to_each_binary(
1126
1244
  monkeypatch: pytest.MonkeyPatch, tmp_path: Path
1127
1245
  ) -> None:
@@ -4,6 +4,16 @@ from pathlib import Path
4
4
  from validate_instruction_pairs import validate_repository
5
5
 
6
6
 
7
+ def read_workflow(workflow_filename: str) -> str:
8
+ workflow_path = (
9
+ Path(__file__).resolve().parents[3]
10
+ / ".github"
11
+ / "workflows"
12
+ / workflow_filename
13
+ )
14
+ return workflow_path.read_text(encoding="utf-8")
15
+
16
+
7
17
  def initialize_repository(repository_root: Path) -> None:
8
18
  subprocess.run(["git", "init", "--quiet"], cwd=repository_root, check=True)
9
19
  subprocess.run(
@@ -88,3 +98,23 @@ def test_untracked_import_fails_tracking_check(tmp_path: Path) -> None:
88
98
  all_errors = validate_repository(tmp_path)
89
99
 
90
100
  assert any("Git mode 100644" in each_error for each_error in all_errors)
101
+
102
+
103
+ def test_pull_request_trigger_is_unconditional() -> None:
104
+ workflow_text = read_workflow("validate-instruction-pairs.yml")
105
+
106
+ assert " pull_request:\n push:\n" in workflow_text
107
+
108
+
109
+ def test_instruction_pairs_status_context_stays_exact() -> None:
110
+ workflow_text = read_workflow("validate-instruction-pairs.yml")
111
+ reusable_workflow_text = read_workflow("instruction-pairs-reusable.yml")
112
+
113
+ assert (
114
+ " instruction-pairs:\n"
115
+ " uses: ./.github/workflows/instruction-pairs-reusable.yml\n"
116
+ " with:\n"
117
+ " validator-ref: ${{ github.event.pull_request.head.sha || github.sha }}\n"
118
+ in workflow_text
119
+ )
120
+ assert " instruction-pairs:\n name: instruction-pairs\n" in reusable_workflow_text
@@ -1,25 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "supportedActivationInterface": "claude-config-dir-mcp-json",
4
- "mcpConfigFileName": "mcp.json",
5
- "bundles": {
6
- "lean": {
7
- "id": "lean",
8
- "allServerNames": ["filesystem-readonly"]
9
- },
10
- "full": {
11
- "id": "full",
12
- "allServerNames": ["filesystem-readonly", "github-readonly"]
13
- }
14
- },
15
- "serverByName": {
16
- "filesystem-readonly": {
17
- "command": "npx",
18
- "args": ["-y", "@modelcontextprotocol/server-filesystem", "${PROFILE_ROOT}"]
19
- },
20
- "github-readonly": {
21
- "command": "npx",
22
- "args": ["-y", "@modelcontextprotocol/server-github"]
23
- }
24
- }
25
- }
@@ -1,60 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
-
5
- const CONFIG_DIRECTORY_PATH = dirname(fileURLToPath(import.meta.url));
6
-
7
- /**
8
- * @param {string} fileName
9
- * @returns {unknown}
10
- */
11
- function readJsonConfigFile(fileName) {
12
- const absolutePath = join(CONFIG_DIRECTORY_PATH, fileName);
13
- return JSON.parse(readFileSync(absolutePath, 'utf8'));
14
- }
15
-
16
- export const PROFILES_MANIFEST_FILE_NAME = 'profiles.manifest.json';
17
- export const SHARED_ALLOWLIST_FILE_NAME = 'shared-allowlist.json';
18
-
19
- /**
20
- * Sole authoritative profile-root environment variable for CLI isolation.
21
- * CLAUDE_HOME is never honored as a profile root by this contract.
22
- */
23
- export const CLAUDE_CONFIG_DIR_ENVIRONMENT_VARIABLE = 'CLAUDE_CONFIG_DIR';
24
- export const CLAUDE_HOME_ENVIRONMENT_VARIABLE = 'CLAUDE_HOME';
25
- export const CLAUDE_CODE_TMPDIR_ENVIRONMENT_VARIABLE = 'CLAUDE_CODE_TMPDIR';
26
- export const CLAUDE_CODE_PLUGIN_SEED_DIR_ENVIRONMENT_VARIABLE = 'CLAUDE_CODE_PLUGIN_SEED_DIR';
27
-
28
- export const PROFILES_ROOT_ENVIRONMENT_VARIABLE = 'LLM_SETTINGS_PROFILES_ROOT';
29
- export const SHARED_SOURCE_ROOT_ENVIRONMENT_VARIABLE = 'LLM_SETTINGS_SHARED_SOURCE_ROOT';
30
- export const PLUGIN_SEED_ROOT_ENVIRONMENT_VARIABLE = 'LLM_SETTINGS_PLUGIN_SEED_ROOT';
31
-
32
- export const DEFAULT_PROFILES_ROOT_DIRECTORY_NAME = '.claude-profiles';
33
- export const DEFAULT_SHARED_SOURCE_DIRECTORY_NAME = 'shared-source';
34
- export const DEFAULT_PLUGIN_SEED_DIRECTORY_NAME = 'plugin-seed';
35
-
36
- export const MIGRATION_MODE_CLEAN_LOCAL_RUNTIME = 'clean-local-runtime';
37
- export const MIGRATION_MODE_MATERIALIZE_FROM_LEGACY = 'materialize-from-legacy';
38
-
39
- export const MCP_BUNDLE_LEAN = 'lean';
40
- export const MCP_BUNDLE_FULL = 'full';
41
-
42
- export const LAUNCHER_SCHEMA_VERSION = 1;
43
- export const PROFILE_ISOLATION_CONTRACT_OWNER = 'profile-isolation-contract';
44
- export const PACKAGE_FILES_WHITELIST_SCRIPTS_ENTRY = 'scripts/';
45
- export const LIVE_DEPLOYMENT_RESERVED_FOR = 'L1';
46
- export const INSTALL_DESTINATION_ROOT_RELATIVE_PATH = 'scripts/profile-isolation-launchers';
47
-
48
- /**
49
- * @returns {Record<string, unknown>}
50
- */
51
- export function loadProfilesManifestDocument() {
52
- return /** @type {Record<string, unknown>} */ (readJsonConfigFile(PROFILES_MANIFEST_FILE_NAME));
53
- }
54
-
55
- /**
56
- * @returns {Record<string, unknown>}
57
- */
58
- export function loadSharedAllowlistDocument() {
59
- return /** @type {Record<string, unknown>} */ (readJsonConfigFile(SHARED_ALLOWLIST_FILE_NAME));
60
- }
@@ -1,54 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "profilesRootPlaceholder": "${PROFILES_ROOT}",
4
- "sharedSourcePlaceholder": "${SHARED_SOURCE_ROOT}",
5
- "pluginSeedPlaceholder": "${PLUGIN_SEED_ROOT}",
6
- "migrationOrder": ["profile-c", "profile-b", "profile-a", "master", "profile-d"],
7
- "profiles": {
8
- "master": {
9
- "id": "master",
10
- "aliases": ["default"],
11
- "directoryName": "master",
12
- "launcherNames": ["claude"],
13
- "fullLauncherNames": ["claude-full"],
14
- "migrationMode": "materialize-from-legacy",
15
- "mcpBundle": "lean"
16
- },
17
- "profile-a": {
18
- "id": "profile-a",
19
- "aliases": [],
20
- "directoryName": "profile-a",
21
- "launcherNames": ["claude-profile-a"],
22
- "fullLauncherNames": ["claude-profile-a-full"],
23
- "migrationMode": "materialize-from-legacy",
24
- "mcpBundle": "lean"
25
- },
26
- "profile-c": {
27
- "id": "profile-c",
28
- "aliases": [],
29
- "directoryName": "profile-c",
30
- "launcherNames": ["claude-profile-c"],
31
- "fullLauncherNames": ["claude-profile-c-full"],
32
- "migrationMode": "clean-local-runtime",
33
- "mcpBundle": "lean"
34
- },
35
- "profile-b": {
36
- "id": "profile-b",
37
- "aliases": [],
38
- "directoryName": "profile-b",
39
- "launcherNames": ["claude-profile-b"],
40
- "fullLauncherNames": ["claude-profile-b-full"],
41
- "migrationMode": "clean-local-runtime",
42
- "mcpBundle": "lean"
43
- },
44
- "profile-d": {
45
- "id": "profile-d",
46
- "aliases": [],
47
- "directoryName": "profile-d",
48
- "launcherNames": ["claude-profile-d"],
49
- "fullLauncherNames": ["claude-profile-d-full"],
50
- "migrationMode": "clean-local-runtime",
51
- "mcpBundle": "lean"
52
- }
53
- }
54
- }
@@ -1,64 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "description": "Read-mostly paths shared across CLI profiles via links. Everything else defaults to physical profile-local.",
4
- "allSharedRelativePaths": [
5
- "CLAUDE.md",
6
- "agents",
7
- "skills",
8
- "rules",
9
- "commands",
10
- "output-styles",
11
- "system-prompts",
12
- "audit-rubrics",
13
- "docs",
14
- "tools",
15
- "hooks",
16
- "scripts"
17
- ],
18
- "allAlwaysLocalRelativePaths": [
19
- ".claude.json",
20
- "settings.json",
21
- "settings.local.json",
22
- "credentials",
23
- ".credentials.json",
24
- "projects",
25
- "sessions",
26
- "history",
27
- "history.jsonl",
28
- "teams",
29
- "tasks",
30
- "jobs",
31
- "daemon",
32
- "plugins",
33
- "marketplaces",
34
- "registries",
35
- "caches",
36
- "file-history",
37
- "shell-snapshots",
38
- "browser",
39
- "data",
40
- "state",
41
- "logs",
42
- "locks",
43
- "offsets",
44
- "telemetry",
45
- "verification",
46
- "backups",
47
- "tmp",
48
- "tmpdir",
49
- "session-env",
50
- "statsig",
51
- "todos",
52
- "plans",
53
- "debug",
54
- ".state",
55
- ".queue"
56
- ],
57
- "allDesktopExcludedPathFragments": [
58
- "Claude Desktop",
59
- "Claude Desktop Profiles",
60
- "CLAUDE_USER_DATA_DIR",
61
- "claude-desktop",
62
- "Claude.exe"
63
- ]
64
- }