claude-dev-env 2.8.0 → 2.10.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.
Files changed (323) hide show
  1. package/CLAUDE.md +8 -2
  2. package/_shared/pr-loop/CLAUDE.md +1 -1
  3. package/_shared/pr-loop/audit-contract.md +17 -6
  4. package/_shared/pr-loop/audit-reply-template.md +4 -4
  5. package/_shared/pr-loop/code-rules-gate.md +3 -5
  6. package/_shared/pr-loop/fix-protocol.md +2 -3
  7. package/_shared/pr-loop/gh-payloads.md +1 -1
  8. package/_shared/pr-loop/scripts/CLAUDE.md +1 -1
  9. package/_shared/pr-loop/scripts/README.md +1 -1
  10. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -0
  11. package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_running.py +16 -1
  12. package/_shared/pr-loop/scripts/code_rules_gate_parts/git_blob_readers.py +11 -5
  13. package/_shared/pr-loop/scripts/preflight.py +9 -4
  14. package/_shared/pr-loop/scripts/reviews_disabled.py +50 -22
  15. package/_shared/pr-loop/scripts/tests/conftest.py +20 -0
  16. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +6 -6
  17. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +50 -6
  18. package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +1 -1
  19. package/_shared/pr-loop/state-schema.md +5 -14
  20. package/agents/CLAUDE.md +2 -2
  21. package/agents/clean-coder.md +62 -562
  22. package/agents/code-quality-agent.md +10 -2
  23. package/agents/code-verifier.md +1 -1
  24. package/agents/test_agent_frontmatter.py +58 -40
  25. package/audit-rubrics/CLAUDE.md +2 -1
  26. package/audit-rubrics/audit-categories.json +704 -0
  27. package/audit-rubrics/prompts/category-i-concurrency.md +1 -1
  28. package/bin/CLAUDE.md +16 -5
  29. package/bin/ever-shipped-skills.mjs +2 -0
  30. package/bin/install-plan.mjs +402 -0
  31. package/bin/install-transaction.mjs +455 -0
  32. package/bin/install.mjs +593 -147
  33. package/bin/install.plan.test.mjs +194 -0
  34. package/bin/install.profile-root.test.mjs +154 -0
  35. package/bin/install.profiles.test.mjs +253 -0
  36. package/bin/install.settings-defaults.test.mjs +200 -0
  37. package/bin/install.transaction.test.mjs +400 -0
  38. package/bin/install.uninstall-transaction.test.mjs +418 -0
  39. package/bin/merge_managed_permissions.mjs +130 -0
  40. package/bin/resolve-install-root.mjs +181 -0
  41. package/bin/select-install-targets.mjs +401 -0
  42. package/commands/CLAUDE.md +0 -2
  43. package/docs/CODE_RULES.md +4 -2
  44. package/docs/references/CLAUDE.md +3 -2
  45. package/docs/references/advisor-tool.md +44 -6
  46. package/docs/references/prose-style-enforcement.md +25 -0
  47. package/docs/references/team-advisor-skill.md +14 -8
  48. package/hooks/blocking/CLAUDE.md +6 -6
  49. package/hooks/blocking/_path_setup.py +9 -5
  50. package/hooks/blocking/code_rules_docstrings.py +124 -30
  51. package/hooks/blocking/code_rules_enforcer.py +161 -16
  52. package/hooks/blocking/code_rules_shared.py +40 -23
  53. package/hooks/blocking/config/CLAUDE.md +3 -5
  54. package/hooks/blocking/config/prose_style_enforcement_constants.py +38 -0
  55. package/hooks/blocking/config/test_prose_style_enforcement_constants.py +45 -0
  56. package/hooks/blocking/eli11_reply_enforcer.py +70 -113
  57. package/hooks/blocking/hedging_language_blocker.py +103 -20
  58. package/hooks/blocking/hook_prose_detector_consistency.py +6 -0
  59. package/hooks/blocking/intent_only_ending_blocker.py +6 -0
  60. package/hooks/blocking/plain_language_blocker.py +139 -20
  61. package/hooks/blocking/pre_tool_use_dispatcher.py +102 -20
  62. package/hooks/blocking/state_description_blocker.py +7 -1
  63. package/hooks/blocking/tdd_enforcer.py +8 -0
  64. package/hooks/blocking/test__path_setup.py +28 -0
  65. package/hooks/blocking/test_code_rules_enforcer_agent_home_tooling.py +99 -0
  66. package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +232 -10
  67. package/hooks/blocking/test_code_rules_enforcer_ephemeral.py +1 -1
  68. package/hooks/blocking/test_code_rules_enforcer_join_separator_magic.py +41 -0
  69. package/hooks/blocking/test_code_rules_enforcer_string_magic.py +98 -0
  70. package/hooks/blocking/test_eli11_reply_enforcer.py +98 -165
  71. package/hooks/blocking/test_hedging_language_blocker.py +120 -1
  72. package/hooks/blocking/test_hook_prose_detector_consistency.py +28 -8
  73. package/hooks/blocking/test_intent_only_ending_blocker.py +27 -2
  74. package/hooks/blocking/test_package_inventory_stale_blocker.py +11 -4
  75. package/hooks/blocking/test_plain_language_blocker.py +129 -19
  76. package/hooks/blocking/test_plain_language_blocker_allowlist.py +70 -26
  77. package/hooks/blocking/test_pre_tool_use_dispatcher.py +99 -26
  78. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +87 -50
  79. package/hooks/blocking/test_state_description_blocker.py +45 -2
  80. package/hooks/blocking/test_stop_dispatcher.py +11 -7
  81. package/hooks/blocking/test_volatile_path_in_post_blocker.py +12 -12
  82. package/hooks/blocking/volatile_path_in_post_blocker.py +2 -2
  83. package/hooks/hooks.json +15 -0
  84. package/hooks/hooks_constants/CLAUDE.md +14 -3
  85. package/hooks/hooks_constants/ask_user_question_shape.py +281 -0
  86. package/hooks/hooks_constants/code_rules_enforcer_constants.py +2 -1
  87. package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -0
  88. package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +5 -12
  89. package/hooks/hooks_constants/hedging_uncertainty_constants.py +42 -0
  90. package/hooks/hooks_constants/issue_tracker_session_starter_constants.py +23 -0
  91. package/hooks/hooks_constants/orchestrator_auto_starter_constants.py +23 -0
  92. package/hooks/hooks_constants/piped_pytest_blocker_constants.py +4 -1
  93. package/hooks/hooks_constants/plain_language_blocker_constants.py +4 -1
  94. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +6 -0
  95. package/hooks/hooks_constants/project_paths_reader.py +31 -4
  96. package/hooks/hooks_constants/prose_matcher_precision_constants.py +40 -0
  97. package/hooks/hooks_constants/pytest_invocation.py +354 -0
  98. package/hooks/hooks_constants/session_start_injector.py +163 -0
  99. package/hooks/hooks_constants/session_start_injector_constants.py +46 -0
  100. package/hooks/hooks_constants/shell_command_pipeline.py +397 -0
  101. package/hooks/hooks_constants/shell_command_segments.py +5 -0
  102. package/hooks/hooks_constants/test_ask_user_question_shape.py +167 -0
  103. package/hooks/hooks_constants/test_project_paths_reader.py +29 -0
  104. package/hooks/hooks_constants/test_prose_metrics_parity.py +8 -0
  105. package/hooks/hooks_constants/test_pytest_invocation.py +130 -0
  106. package/hooks/hooks_constants/test_session_start_injector.py +168 -0
  107. package/hooks/hooks_constants/test_shell_command_pipeline.py +135 -0
  108. package/hooks/hooks_constants/volatile_path_in_post_blocker_constants.py +1 -1
  109. package/hooks/hooks_constants/working_style_prompt_constants.py +30 -0
  110. package/hooks/observability/CLAUDE.md +2 -0
  111. package/hooks/observability/prose_matcher_advisory.py +237 -0
  112. package/hooks/observability/test_prose_matcher_advisory.py +143 -0
  113. package/hooks/session/CLAUDE.md +9 -1
  114. package/hooks/session/_path_setup.py +13 -0
  115. package/hooks/session/issue_tracker_session_starter.py +135 -0
  116. package/hooks/session/orchestrator_auto_starter.py +100 -0
  117. package/hooks/session/test__path_setup.py +28 -0
  118. package/hooks/session/test_issue_tracker_session_starter.py +104 -0
  119. package/hooks/session/test_orchestrator_auto_starter.py +99 -0
  120. package/hooks/session/test_working_style_prompt.py +47 -0
  121. package/hooks/session/untracked_repo_detector.py +1 -24
  122. package/hooks/session/working_style_prompt.py +36 -0
  123. package/hooks/validators/_path_setup.py +19 -0
  124. package/hooks/validators/run_all_validators.py +8 -13
  125. package/installable-surfaces.manifest.json +21 -0
  126. package/output-styles/CLAUDE.md +15 -0
  127. package/package.json +5 -2
  128. package/rules/CLAUDE.md +1 -0
  129. package/rules/code-standards.md +33 -7
  130. package/rules/durable-post-artifacts.md +2 -2
  131. package/rules/eli11-replies.md +7 -2
  132. package/rules/hedging-claims.md +4 -2
  133. package/rules/long-horizon-autonomy.md +3 -1
  134. package/rules/opus5-communication-contract.md +45 -0
  135. package/rules/plain-language.md +2 -2
  136. package/rules/research-mode.md +1 -1
  137. package/scripts/CLAUDE.md +13 -2
  138. package/scripts/Sync-RepoMain.ps1 +215 -0
  139. package/scripts/active_capability_references.py +218 -0
  140. package/scripts/ci/windows-installer-lifecycle.ps1 +78 -0
  141. package/scripts/claude_chain_runner.py +394 -6
  142. package/scripts/claude_chain_usage.py +1 -1
  143. package/scripts/codex_compat_materializer.py +105 -85
  144. package/scripts/dev_env_scripts_constants/CLAUDE.md +3 -1
  145. package/scripts/dev_env_scripts_constants/active_capability_constants.py +46 -0
  146. package/scripts/dev_env_scripts_constants/claude_chain_constants.py +74 -0
  147. package/scripts/dev_env_scripts_constants/grok_run_ledger_constants.py +50 -0
  148. package/scripts/dev_env_scripts_constants/grok_worker_constants.py +104 -0
  149. package/scripts/dev_env_scripts_constants/verify_installable_package_constants.py +116 -0
  150. package/scripts/grok_patch_artifacts.py +123 -0
  151. package/scripts/grok_run_ledger.py +318 -0
  152. package/scripts/profile-isolation-launchers/config/mcp-bundles.json +25 -0
  153. package/scripts/profile-isolation-launchers/config/profile-isolation-constants.mjs +60 -0
  154. package/scripts/profile-isolation-launchers/config/profiles.manifest.json +54 -0
  155. package/scripts/profile-isolation-launchers/config/shared-allowlist.json +64 -0
  156. package/scripts/profile-isolation-launchers/launcher-runtime.mjs +180 -0
  157. package/scripts/profile-isolation-launchers/lib/profile-manifest.mjs +288 -0
  158. package/scripts/profile-isolation-launchers/mcp-bundles.mjs +275 -0
  159. package/scripts/profile-isolation-launchers/profile-isolation-contract.test.mjs +221 -0
  160. package/scripts/profile-isolation-launchers/tests/launcher-runtime.test.mjs +108 -0
  161. package/scripts/profile-isolation-launchers/tests/mcp-bundles.test.mjs +147 -0
  162. package/scripts/profile-isolation-launchers/tests/shortcut-contract.test.ps1 +102 -0
  163. package/scripts/profile-isolation-launchers/tests/version-compatibility.test.mjs +210 -0
  164. package/scripts/profile-isolation-launchers/version-compatibility.mjs +299 -0
  165. package/scripts/profile-isolation-launchers/windows/shortcut-inventory.ps1 +127 -0
  166. package/scripts/profile-isolation-launchers/windows/shortcut-manifest.json +51 -0
  167. package/scripts/profile-isolation-launchers/windows/shortcut-reconcile.ps1 +77 -0
  168. package/scripts/spawn_grok_batch.py +556 -9
  169. package/scripts/test_active_capability_references.py +108 -0
  170. package/scripts/test_claude_chain_runner.py +414 -82
  171. package/scripts/test_claude_chain_usage.py +12 -12
  172. package/scripts/test_grok_patch_artifacts.py +82 -0
  173. package/scripts/test_grok_run_ledger.py +116 -0
  174. package/scripts/test_resolve_worker_spawn.py +2 -2
  175. package/scripts/test_spawn_grok_batch.py +295 -0
  176. package/scripts/test_verify_installable_package.py +208 -0
  177. package/scripts/tests/test_codex_compat_materializer.py +33 -0
  178. package/scripts/verify_installable_package.py +612 -0
  179. package/settings.json +10 -0
  180. package/skills/CLAUDE.md +6 -2
  181. package/skills/_shared/CLAUDE.md +37 -4
  182. package/skills/_shared/advisor/CLAUDE.md +9 -0
  183. package/skills/_shared/advisor/advisor-protocol.md +5 -0
  184. package/skills/_shared/advisor/scripts/README.md +9 -0
  185. package/skills/_shared/end-of-run-gotcha-recommendations.md +156 -0
  186. package/skills/_shared/pr-loop/CLAUDE.md +18 -1
  187. package/skills/_shared/pr-loop/audit-contract.md +5 -0
  188. package/skills/_shared/pr-loop/audit-reply-template.md +5 -0
  189. package/skills/_shared/pr-loop/code-rules-gate.md +5 -0
  190. package/skills/_shared/pr-loop/fix-protocol.md +5 -0
  191. package/skills/_shared/pr-loop/gh-payloads.md +5 -0
  192. package/skills/_shared/pr-loop/post-audit-thread-contract.md +5 -0
  193. package/skills/_shared/pr-loop/precatch-rubric.md +5 -0
  194. package/skills/_shared/pr-loop/scripts/CLAUDE.md +9 -1
  195. package/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +29 -0
  196. package/skills/_shared/pr-loop/scripts/audit_category_schema.py +355 -0
  197. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -0
  198. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +32 -0
  199. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +7 -19
  200. package/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +94 -0
  201. package/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +21 -0
  202. package/skills/_shared/pr-loop/state-schema.md +5 -0
  203. package/skills/_shared/pr-loop/worker-spawn.md +5 -0
  204. package/skills/autoconverge/reference/convergence.md +2 -1
  205. package/skills/autoconverge/reference/stop-conditions.md +5 -3
  206. package/skills/beat-sheet/SKILL.md +54 -0
  207. package/skills/beat-sheet/reference/visual-beats.md +29 -0
  208. package/skills/bugteam/CONSTRAINTS.md +4 -4
  209. package/skills/bugteam/EXAMPLES.md +1 -1
  210. package/skills/bugteam/reference/README.md +1 -1
  211. package/skills/e-code-review/SKILL.md +29 -3
  212. package/skills/e-code-review/reference/effort-evaluation.md +35 -0
  213. package/skills/e-code-review/reference/medium.md +15 -4
  214. package/skills/e-code-review/reference/runner-selection.md +40 -0
  215. package/skills/e-code-review/scripts/config/e_code_review_effort_constants/__init__.py +41 -0
  216. package/skills/e-code-review/scripts/config/e_code_review_effort_constants/effort_constants.py +40 -0
  217. package/skills/e-code-review/scripts/e_code_review_scripts_constants/__init__.py +1 -0
  218. package/skills/e-code-review/scripts/e_code_review_scripts_constants/finding_pipeline_constants.py +49 -0
  219. package/skills/e-code-review/scripts/e_code_review_scripts_constants/grok_code_review_constants.py +55 -0
  220. package/skills/e-code-review/scripts/effort_defaults_evidence.json +186 -0
  221. package/skills/e-code-review/scripts/effort_evaluation.py +362 -0
  222. package/skills/e-code-review/scripts/finding_pipeline.py +140 -0
  223. package/skills/e-code-review/scripts/fixtures/demanding.json +26 -0
  224. package/skills/e-code-review/scripts/fixtures/easy.json +14 -0
  225. package/skills/e-code-review/scripts/fixtures/medium.json +20 -0
  226. package/skills/e-code-review/scripts/grok_code_review.py +230 -0
  227. package/skills/e-code-review/scripts/test_effort_evaluation.py +180 -0
  228. package/skills/e-code-review/scripts/test_finding_pipeline.py +197 -0
  229. package/skills/e-code-review/scripts/test_grok_code_review.py +289 -0
  230. package/skills/grok-spawn/SKILL.md +5 -0
  231. package/skills/orchestrator/SKILL.md +5 -0
  232. package/skills/plan-to-pr/scripts/create_packet.py +4 -4
  233. package/skills/plan-to-pr/scripts/load_skill_constants.py +41 -0
  234. package/skills/plan-to-pr/scripts/validate_packet.py +4 -4
  235. package/skills/plan-to-pr/scripts/validate_protocol.py +4 -1
  236. package/skills/plan-to-pr/scripts/validate_run.py +4 -1
  237. package/skills/pr-converge/scripts/check_convergence.py +21 -19
  238. package/skills/pr-converge/scripts/check_convergence_availability.py +50 -7
  239. package/skills/pr-converge/scripts/conftest.py +35 -0
  240. package/skills/pr-converge/scripts/test_check_convergence_availability.py +65 -0
  241. package/skills/pr-converge/scripts/test_check_convergence_codex.py +11 -1
  242. package/skills/pr-converge/scripts/test_check_convergence_contract.py +9 -2
  243. package/skills/pr-loop-cloud-transport/SKILL.md +1 -1
  244. package/skills/rebase/SKILL.md +15 -3
  245. package/skills/reviewer-gates/SKILL.md +2 -2
  246. package/skills/show/SKILL.md +51 -0
  247. package/skills/show/references/accessibility.md +7 -0
  248. package/skills/show/references/art.md +3 -0
  249. package/skills/show/references/charts.md +3 -0
  250. package/skills/show/references/core-design.md +14 -0
  251. package/skills/show/references/erds.md +3 -0
  252. package/skills/show/references/flowcharts.md +3 -0
  253. package/skills/show/references/host-and-html.md +3 -0
  254. package/skills/show/references/illustrative-diagrams.md +10 -0
  255. package/skills/show/references/interaction.md +3 -0
  256. package/skills/show/references/mockups.md +3 -0
  257. package/skills/show/references/quality-gates.md +7 -0
  258. package/skills/show/references/structural-diagrams.md +3 -0
  259. package/skills/show/references/subject-inventory.md +21 -0
  260. package/skills/show/references/svg-contract.md +22 -0
  261. package/skills/show/routing.yaml +30 -0
  262. package/skills/show/samples/pr1262-v2.svg +222 -0
  263. package/skills/show/scripts/README.md +6 -0
  264. package/skills/show/scripts/validate-artifact.py +91 -0
  265. package/skills/show/scripts/validate-package.py +18 -0
  266. package/skills/show/templates/html-widget.html +4 -0
  267. package/skills/show/templates/svg-base.svg +19 -0
  268. package/skills/show/tests/fixtures/css-var.svg +6 -0
  269. package/skills/show/tests/fixtures/dead-ref.svg +7 -0
  270. package/skills/show/tests/fixtures/filled-glyph.svg +8 -0
  271. package/skills/show/tests/fixtures/inherited-fill.svg +18 -0
  272. package/skills/show/tests/fixtures/invalid.svg +1 -0
  273. package/skills/show/tests/fixtures/large-canvas.svg +21 -0
  274. package/skills/show/tests/fixtures/unfilled-connector.svg +15 -0
  275. package/skills/show/tests/fixtures/valid.html +1 -0
  276. package/skills/show/tests/test_validate-artifact.py +74 -0
  277. package/skills/show/tests/test_validators.py +59 -0
  278. package/skills/show/workflows/create-visual.md +13 -0
  279. package/skills/show/workflows/review-visual.md +20 -0
  280. package/skills/split-pr/SKILL.md +85 -0
  281. package/skills/split-pr/reference/path-layers.md +16 -0
  282. package/skills/split-pr/reference/proposal-format.md +15 -0
  283. package/skills/split-pr/reference/split-further-loop.md +10 -0
  284. package/skills/split-pr/reference/splitting-principles.md +26 -0
  285. package/skills/split-pr/scripts/analyze_pr.py +279 -0
  286. package/skills/split-pr/scripts/categorize_files.py +106 -0
  287. package/skills/split-pr/scripts/config/__init__.py +1 -0
  288. package/skills/split-pr/scripts/config/dependency_constants.py +14 -0
  289. package/skills/split-pr/scripts/config/git_operations_constants.py +36 -0
  290. package/skills/split-pr/scripts/config/packing_constants.py +61 -0
  291. package/skills/split-pr/scripts/config/plan_constants.py +49 -0
  292. package/skills/split-pr/scripts/config/split_pr_constants.py +110 -0
  293. package/skills/split-pr/scripts/execute_split_slices.py +82 -0
  294. package/skills/split-pr/scripts/pack_files_into_slices.py +212 -0
  295. package/skills/split-pr/scripts/split_pr_dependency_graph.py +70 -0
  296. package/skills/split-pr/scripts/split_pr_git_operations.py +184 -0
  297. package/skills/split-pr/scripts/split_pr_layer_order.py +58 -0
  298. package/skills/split-pr/scripts/split_pr_paginate.py +119 -0
  299. package/skills/split-pr/scripts/split_pr_process_runner.py +52 -0
  300. package/skills/split-pr/scripts/split_pr_script_types.py +126 -0
  301. package/skills/split-pr/scripts/split_pr_title.py +41 -0
  302. package/skills/split-pr/scripts/test_analyze_pr.py +228 -0
  303. package/skills/split-pr/scripts/test_categorize_files.py +55 -0
  304. package/skills/split-pr/scripts/test_categorize_files_packing.py +59 -0
  305. package/skills/split-pr/scripts/test_execute_split_slices.py +99 -0
  306. package/skills/split-pr/scripts/test_split_pr_dependency_graph.py +47 -0
  307. package/skills/split-pr/scripts/test_split_pr_git_operations.py +125 -0
  308. package/skills/split-pr/scripts/test_split_pr_layer_order.py +36 -0
  309. package/skills/split-pr/scripts/test_split_pr_paginate.py +65 -0
  310. package/skills/split-pr/scripts/test_split_pr_script_types.py +73 -0
  311. package/skills/split-pr/scripts/test_split_pr_title.py +28 -0
  312. package/skills/split-pr/scripts/test_verify_dependency_graph.py +46 -0
  313. package/skills/split-pr/scripts/test_verify_plan.py +56 -0
  314. package/skills/split-pr/scripts/test_verify_plan_contract.py +50 -0
  315. package/skills/split-pr/scripts/test_verify_plan_path_normalization.py +45 -0
  316. package/skills/split-pr/scripts/verify_dependency_graph.py +111 -0
  317. package/skills/split-pr/scripts/verify_plan.py +139 -0
  318. package/skills/task-build/reference/tool-routing.md +3 -0
  319. package/skills/team-advisor/SKILL.md +23 -44
  320. package/system-prompts/software-engineer.xml +17 -5
  321. package/commands/initialize.md +0 -90
  322. package/commands/stubcheck.md +0 -88
  323. package/skills/test_markdown_link_integrity.py +0 -107
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python3
2
+ """Extract patch artifacts and SHA-256 manifests from isolated worktrees.
3
+
4
+ ::
5
+
6
+ manifest = write_patch_manifest(
7
+ run_state_directory=run_dir,
8
+ task_id="O-04",
9
+ base_sha="abc",
10
+ worktree_path=worktree,
11
+ worker_report_text="ok",
12
+ )
13
+ ok: manifest carries content hash and changed paths
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import hashlib
19
+ import json
20
+ import subprocess
21
+ from pathlib import Path
22
+
23
+ from dev_env_scripts_constants.grok_run_ledger_constants import (
24
+ JSON_INDENT,
25
+ LEDGER_SCHEMA_VERSION,
26
+ PATCH_MANIFEST_FILENAME,
27
+ UTF8_ENCODING,
28
+ )
29
+
30
+
31
+ def compute_sha256_hex(content: bytes) -> str:
32
+ """Return the hex SHA-256 digest of raw bytes.
33
+
34
+ Args:
35
+ content: Bytes to hash.
36
+
37
+ Returns:
38
+ Lowercase hex digest string.
39
+ """
40
+ return hashlib.sha256(content).hexdigest()
41
+
42
+
43
+ def extract_worktree_diff(
44
+ *,
45
+ worktree_path: Path,
46
+ base_sha: str,
47
+ ) -> tuple[str, tuple[str, ...]]:
48
+ """Return unified diff text and changed paths against base_sha.
49
+
50
+ Args:
51
+ worktree_path: Isolated worker worktree.
52
+ base_sha: Base commit SHA the worker started from.
53
+
54
+ Returns:
55
+ ``(diff_text, changed_paths)``.
56
+ """
57
+ diff_text = subprocess.check_output(
58
+ ["git", "-C", str(worktree_path), "diff", base_sha],
59
+ text=True,
60
+ encoding=UTF8_ENCODING,
61
+ )
62
+ changed_paths_listing = subprocess.check_output(
63
+ ["git", "-C", str(worktree_path), "diff", "--name-only", base_sha],
64
+ text=True,
65
+ encoding=UTF8_ENCODING,
66
+ )
67
+ changed_paths = tuple(
68
+ each_line.strip()
69
+ for each_line in changed_paths_listing.splitlines()
70
+ if each_line.strip()
71
+ )
72
+ return diff_text, changed_paths
73
+
74
+
75
+ def write_patch_manifest(
76
+ *,
77
+ run_state_directory: Path,
78
+ task_id: str,
79
+ base_sha: str,
80
+ worktree_path: Path,
81
+ worker_report_text: str,
82
+ patch_filename: str | None = None,
83
+ ) -> dict[str, object]:
84
+ """Write a patch file and JSON manifest binding hashes and paths.
85
+
86
+ Args:
87
+ run_state_directory: Directory that holds ledger and patch artifacts.
88
+ task_id: Task the patch belongs to.
89
+ base_sha: Base commit SHA.
90
+ worktree_path: Worker worktree to diff.
91
+ worker_report_text: Worker report body bound into the manifest.
92
+ patch_filename: Optional override for the ``.patch`` filename.
93
+
94
+ Returns:
95
+ The manifest document written to disk.
96
+ """
97
+ run_state_directory = Path(run_state_directory)
98
+ run_state_directory.mkdir(parents=True, exist_ok=True)
99
+ diff_text, changed_paths = extract_worktree_diff(
100
+ worktree_path=Path(worktree_path),
101
+ base_sha=base_sha,
102
+ )
103
+ patch_name = patch_filename or f"{task_id}.patch"
104
+ patch_path = run_state_directory / patch_name
105
+ patch_bytes = diff_text.encode(UTF8_ENCODING)
106
+ patch_path.write_bytes(patch_bytes)
107
+ content_hash = compute_sha256_hex(patch_bytes)
108
+ report_hash = compute_sha256_hex(worker_report_text.encode(UTF8_ENCODING))
109
+ manifest = {
110
+ "schema_version": LEDGER_SCHEMA_VERSION,
111
+ "task_id": task_id,
112
+ "base_sha": base_sha,
113
+ "changed_paths": list(changed_paths),
114
+ "patch_path": str(patch_path),
115
+ "content_sha256": content_hash,
116
+ "worker_report_sha256": report_hash,
117
+ }
118
+ manifest_path = run_state_directory / PATCH_MANIFEST_FILENAME
119
+ manifest_path.write_text(
120
+ json.dumps(manifest, indent=JSON_INDENT) + "\n",
121
+ encoding=UTF8_ENCODING,
122
+ )
123
+ return manifest
@@ -0,0 +1,318 @@
1
+ #!/usr/bin/env python3
2
+ """Host-neutral file-backed ledger for Grok orchestration task state.
3
+
4
+ Records every delegated unit before dispatch, enforces one live owner and one
5
+ unique advisor session per in-progress task, blocks on unfinished dependencies,
6
+ and reopens tasks when the base snapshot drifts.
7
+
8
+ ::
9
+
10
+ ledger = GrokRunLedger(run_state_directory)
11
+ ledger.register_task(task_id="O-04", dependencies=())
12
+ ledger.mark_in_progress(
13
+ task_id="O-04",
14
+ owner_id="worker-1",
15
+ advisor_session_id="sess-1",
16
+ base_sha="abc",
17
+ )
18
+ ok: task status becomes in_progress with that owner and session
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import json
24
+ import os
25
+ import tempfile
26
+ from dataclasses import asdict, dataclass, field
27
+ from pathlib import Path
28
+
29
+ from dev_env_scripts_constants.grok_run_ledger_constants import (
30
+ ALL_LEGAL_TASK_STATUSES,
31
+ JSON_INDENT,
32
+ LEDGER_FILENAME,
33
+ LEDGER_SCHEMA_VERSION,
34
+ TASK_STATUS_ADVISOR_BLOCKED,
35
+ TASK_STATUS_COMPLETED,
36
+ TASK_STATUS_IN_PROGRESS,
37
+ TASK_STATUS_PENDING,
38
+ TASK_STATUS_PENDING_REVIEW,
39
+ TEMPORARY_LEDGER_PREFIX,
40
+ TEMPORARY_LEDGER_SUFFIX,
41
+ UTF8_ENCODING,
42
+ )
43
+
44
+
45
+ @dataclass
46
+ class LedgerTaskRecord:
47
+ """One delegated unit tracked in the run ledger."""
48
+
49
+ task_id: str
50
+ status: str = TASK_STATUS_PENDING
51
+ dependencies: tuple[str, ...] = ()
52
+ owner_id: str | None = None
53
+ advisor_session_id: str | None = None
54
+ advisor_verdict: str | None = None
55
+ base_sha: str | None = None
56
+ reviewed_head: str | None = None
57
+ changed_paths: tuple[str, ...] = ()
58
+ acceptance_mapping: dict[str, str] = field(default_factory=dict)
59
+ test_evidence: list[str] = field(default_factory=list)
60
+
61
+
62
+ class GrokRunLedger:
63
+ """Atomic file-backed ledger: register_task, get_task, can_dispatch, mark_in_progress, mark_completed, mark_advisor_blocked, invalidate_on_snapshot_drift, all_tasks."""
64
+
65
+ def __init__(self, run_state_directory: Path) -> None:
66
+ self.run_state_directory = Path(run_state_directory)
67
+ self.ledger_path = self.run_state_directory / LEDGER_FILENAME
68
+ self._task_by_id: dict[str, LedgerTaskRecord] = {}
69
+ self.run_state_directory.mkdir(parents=True, exist_ok=True)
70
+ if self.ledger_path.is_file():
71
+ self._load()
72
+
73
+ def _load(self) -> None:
74
+ payload = json.loads(self.ledger_path.read_text(encoding=UTF8_ENCODING))
75
+ for each_task in payload.get("tasks", []):
76
+ record = LedgerTaskRecord(
77
+ task_id=each_task["task_id"],
78
+ status=each_task["status"],
79
+ dependencies=tuple(each_task.get("dependencies") or ()),
80
+ owner_id=each_task.get("owner_id"),
81
+ advisor_session_id=each_task.get("advisor_session_id"),
82
+ advisor_verdict=each_task.get("advisor_verdict"),
83
+ base_sha=each_task.get("base_sha"),
84
+ reviewed_head=each_task.get("reviewed_head"),
85
+ changed_paths=tuple(each_task.get("changed_paths") or ()),
86
+ acceptance_mapping=dict(each_task.get("acceptance_mapping") or {}),
87
+ test_evidence=list(each_task.get("test_evidence") or []),
88
+ )
89
+ self._task_by_id[record.task_id] = record
90
+
91
+ def _atomic_write(self) -> None:
92
+ document = {
93
+ "schema_version": LEDGER_SCHEMA_VERSION,
94
+ "tasks": [
95
+ {
96
+ **asdict(each_record),
97
+ "dependencies": list(each_record.dependencies),
98
+ "changed_paths": list(each_record.changed_paths),
99
+ }
100
+ for each_record in sorted(
101
+ self._task_by_id.values(), key=lambda item: item.task_id
102
+ )
103
+ ],
104
+ }
105
+ encoded = json.dumps(document, indent=JSON_INDENT) + "\n"
106
+ file_descriptor, temporary_path = tempfile.mkstemp(
107
+ dir=self.run_state_directory,
108
+ prefix=TEMPORARY_LEDGER_PREFIX,
109
+ suffix=TEMPORARY_LEDGER_SUFFIX,
110
+ )
111
+ try:
112
+ with os.fdopen(file_descriptor, "w", encoding=UTF8_ENCODING) as handle:
113
+ handle.write(encoded)
114
+ handle.flush()
115
+ os.fsync(handle.fileno())
116
+ os.replace(temporary_path, self.ledger_path)
117
+ except (OSError, TypeError, ValueError):
118
+ if os.path.exists(temporary_path):
119
+ os.unlink(temporary_path)
120
+ raise
121
+
122
+ def register_task(
123
+ self,
124
+ *,
125
+ task_id: str,
126
+ all_dependencies: tuple[str, ...] = (),
127
+ ) -> LedgerTaskRecord:
128
+ """Record a delegated unit before dispatch.
129
+
130
+ Args:
131
+ task_id: Stable task identifier.
132
+ all_dependencies: Task ids that must complete before dispatch.
133
+
134
+ Returns:
135
+ The registered pending task record.
136
+
137
+ Raises:
138
+ ValueError: When the task id already exists.
139
+ """
140
+ if task_id in self._task_by_id:
141
+ raise ValueError(f"task already registered: {task_id}")
142
+ record = LedgerTaskRecord(
143
+ task_id=task_id,
144
+ status=TASK_STATUS_PENDING,
145
+ dependencies=all_dependencies,
146
+ )
147
+ self._task_by_id[task_id] = record
148
+ self._atomic_write()
149
+ return record
150
+
151
+ def get_task(self, task_id: str) -> LedgerTaskRecord:
152
+ """Return one task record.
153
+
154
+ Args:
155
+ task_id: Stable task identifier.
156
+
157
+ Returns:
158
+ The stored task record.
159
+
160
+ Raises:
161
+ KeyError: When the task id is unknown.
162
+ """
163
+ return self._task_by_id[task_id]
164
+
165
+ def can_dispatch(self, task_id: str) -> bool:
166
+ """Return whether every dependency has completed successfully.
167
+
168
+ Args:
169
+ task_id: Task to evaluate.
170
+
171
+ Returns:
172
+ True when every dependency is ``completed``.
173
+ """
174
+ record = self.get_task(task_id)
175
+ for each_dependency in record.dependencies:
176
+ dependency_record = self._task_by_id.get(each_dependency)
177
+ if dependency_record is None:
178
+ return False
179
+ if dependency_record.status != TASK_STATUS_COMPLETED:
180
+ return False
181
+ return True
182
+
183
+ def mark_in_progress(
184
+ self,
185
+ *,
186
+ task_id: str,
187
+ owner_id: str,
188
+ advisor_session_id: str,
189
+ base_sha: str,
190
+ ) -> LedgerTaskRecord:
191
+ """Assign one owner and unique advisor session and start the task.
192
+
193
+ Args:
194
+ task_id: Task to start.
195
+ owner_id: Live owner identity.
196
+ advisor_session_id: Unique advisor session for this worker.
197
+ base_sha: Snapshot SHA at dispatch.
198
+
199
+ Returns:
200
+ The updated task record.
201
+
202
+ Raises:
203
+ ValueError: When dispatch is blocked, another owner is live, the
204
+ advisor session is reused, or status is illegal.
205
+ """
206
+ if not self.can_dispatch(task_id):
207
+ raise ValueError(f"dependencies incomplete for {task_id}")
208
+ for each_record in self._task_by_id.values():
209
+ if (
210
+ each_record.status == TASK_STATUS_IN_PROGRESS
211
+ and each_record.owner_id == owner_id
212
+ and each_record.task_id != task_id
213
+ ):
214
+ raise ValueError(f"owner already live on {each_record.task_id}")
215
+ if (
216
+ each_record.advisor_session_id == advisor_session_id
217
+ and each_record.task_id != task_id
218
+ ):
219
+ raise ValueError(
220
+ f"advisor session already bound to {each_record.task_id}"
221
+ )
222
+ record = self.get_task(task_id)
223
+ if record.status not in {TASK_STATUS_PENDING, TASK_STATUS_PENDING_REVIEW}:
224
+ raise ValueError(f"cannot start task from status {record.status}")
225
+ record.status = TASK_STATUS_IN_PROGRESS
226
+ record.owner_id = owner_id
227
+ record.advisor_session_id = advisor_session_id
228
+ record.base_sha = base_sha
229
+ self._atomic_write()
230
+ return record
231
+
232
+ def mark_completed(
233
+ self,
234
+ *,
235
+ task_id: str,
236
+ reviewed_head: str,
237
+ all_changed_paths: tuple[str, ...],
238
+ advisor_verdict: str,
239
+ all_acceptance_mapping: dict[str, str],
240
+ all_test_evidence: list[str],
241
+ ) -> LedgerTaskRecord:
242
+ """Record successful terminal state for an in-progress task.
243
+
244
+ Args:
245
+ task_id: Task to complete.
246
+ reviewed_head: Final reviewed commit SHA.
247
+ all_changed_paths: Paths changed by the worker.
248
+ advisor_verdict: Opening advisor signal (for example ENDORSE).
249
+ all_acceptance_mapping: Acceptance criterion to evidence map.
250
+ all_test_evidence: Commands or artifacts proving tests.
251
+
252
+ Returns:
253
+ The completed task record.
254
+
255
+ Raises:
256
+ ValueError: When the task is not in progress.
257
+ """
258
+ record = self.get_task(task_id)
259
+ if record.status != TASK_STATUS_IN_PROGRESS:
260
+ raise ValueError(f"cannot complete task from status {record.status}")
261
+ record.status = TASK_STATUS_COMPLETED
262
+ record.reviewed_head = reviewed_head
263
+ record.changed_paths = all_changed_paths
264
+ record.advisor_verdict = advisor_verdict
265
+ record.acceptance_mapping = dict(all_acceptance_mapping)
266
+ record.test_evidence = list(all_test_evidence)
267
+ self._atomic_write()
268
+ return record
269
+
270
+ def mark_advisor_blocked(self, *, task_id: str, reason: str) -> LedgerTaskRecord:
271
+ """Stop a task because the advisor path failed closed.
272
+
273
+ Args:
274
+ task_id: Task to block.
275
+ reason: Short failure reason stored in test evidence.
276
+
277
+ Returns:
278
+ The blocked task record.
279
+ """
280
+ record = self.get_task(task_id)
281
+ record.status = TASK_STATUS_ADVISOR_BLOCKED
282
+ record.test_evidence = [reason]
283
+ self._atomic_write()
284
+ return record
285
+
286
+ def invalidate_on_snapshot_drift(
287
+ self,
288
+ *,
289
+ task_id: str,
290
+ current_sha: str,
291
+ ) -> LedgerTaskRecord:
292
+ """Move a task back to pending review when the base snapshot drifts.
293
+
294
+ Args:
295
+ task_id: Task to invalidate.
296
+ current_sha: Live SHA compared to the recorded base.
297
+
298
+ Returns:
299
+ The updated task record (unchanged when SHAs match).
300
+ """
301
+ record = self.get_task(task_id)
302
+ if record.base_sha is None or record.base_sha == current_sha:
303
+ return record
304
+ record.status = TASK_STATUS_PENDING_REVIEW
305
+ record.owner_id = None
306
+ self._atomic_write()
307
+ return record
308
+
309
+ def all_tasks(self) -> tuple[LedgerTaskRecord, ...]:
310
+ """Return every task record sorted by task id."""
311
+ return tuple(
312
+ sorted(self._task_by_id.values(), key=lambda item: item.task_id)
313
+ )
314
+
315
+
316
+ def is_legal_status(status: str) -> bool:
317
+ """Return whether a status token is in the legal set."""
318
+ return status in ALL_LEGAL_TASK_STATUSES
@@ -0,0 +1,25 @@
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
+ }
@@ -0,0 +1,60 @@
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
+ }
@@ -0,0 +1,54 @@
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
+ }
@@ -0,0 +1,64 @@
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
+ }