claude-dev-env 1.92.1 → 1.93.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 (215) hide show
  1. package/CLAUDE.md +6 -2
  2. package/_shared/CLAUDE.md +2 -1
  3. package/_shared/advisor/CLAUDE.md +21 -0
  4. package/_shared/advisor/advisor-protocol.md +142 -0
  5. package/_shared/advisor/scripts/config/advisor_scripts_constants/__init__.py +1 -0
  6. package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +86 -0
  7. package/_shared/advisor/scripts/model_tier_run_validator.py +246 -0
  8. package/_shared/advisor/scripts/pyproject.toml +3 -0
  9. package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +302 -0
  10. package/_shared/advisor/scripts/tests/test_tier_model_ids.py +180 -0
  11. package/_shared/advisor/scripts/tier_model_ids.py +164 -0
  12. package/_shared/pr-loop/CLAUDE.md +1 -0
  13. package/_shared/pr-loop/precatch-rubric.md +65 -0
  14. package/_shared/pr-loop/scripts/CLAUDE.md +1 -1
  15. package/_shared/pr-loop/scripts/code_rules_gate.py +260 -14
  16. package/_shared/pr-loop/scripts/post_audit_thread.py +1 -1
  17. package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -1
  18. package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +20 -0
  19. package/_shared/pr-loop/scripts/pr_loop_shared_constants/reviews_disabled_constants.py +2 -1
  20. package/_shared/pr-loop/scripts/reviewer_availability.py +42 -12
  21. package/_shared/pr-loop/scripts/reviews_disabled.py +65 -21
  22. package/_shared/pr-loop/scripts/terminology_sweep.py +69 -21
  23. package/_shared/pr-loop/scripts/tests/CLAUDE.md +1 -1
  24. package/_shared/pr-loop/scripts/tests/fixtures/{copilot_internal_user_jonecho.json → copilot_internal_user_example.json} +1 -1
  25. package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +1 -1
  26. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +292 -2
  27. package/_shared/pr-loop/scripts/tests/test_copilot_quota.py +8 -8
  28. package/_shared/pr-loop/scripts/tests/test_reviewer_availability.py +18 -5
  29. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +56 -5
  30. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +104 -17
  31. package/agents/CLAUDE.md +3 -2
  32. package/agents/clasp-deployment-orchestrator.md +2 -2
  33. package/agents/code-advisor.md +7 -5
  34. package/agents/code-verifier.md +6 -2
  35. package/agents/session-advisor.md +27 -0
  36. package/audit-rubrics/category_rubrics/category-j-code-rules-compliance.md +1 -1
  37. package/audit-rubrics/category_rubrics/category-k-codebase-conflicts.md +1 -1
  38. package/audit-rubrics/prompts/category-a-api-contracts.md +2 -2
  39. package/audit-rubrics/prompts/category-b-selector-engine-compat.md +2 -2
  40. package/audit-rubrics/prompts/category-c-resource-cleanup.md +2 -2
  41. package/audit-rubrics/prompts/category-d-scoping-and-ordering.md +2 -2
  42. package/audit-rubrics/prompts/category-e-dead-code.md +2 -2
  43. package/audit-rubrics/prompts/category-f-silent-failures.md +2 -2
  44. package/audit-rubrics/prompts/category-g-bounds-and-overflow.md +2 -2
  45. package/audit-rubrics/prompts/category-h-security-boundaries.md +2 -2
  46. package/audit-rubrics/prompts/category-i-concurrency.md +2 -2
  47. package/audit-rubrics/prompts/category-j-code-rules-compliance.md +2 -2
  48. package/audit-rubrics/prompts/category-k-codebase-conflicts.md +2 -2
  49. package/audit-rubrics/prompts/category-l-behavior-equivalence.md +2 -2
  50. package/audit-rubrics/prompts/category-m-producer-consumer-cardinality.md +2 -2
  51. package/audit-rubrics/prompts/category-n-test-name-scenario-verifier.md +2 -2
  52. package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
  53. package/audit-rubrics/prompts/category-p-name-vs-behavior-contract.md +2 -2
  54. package/bin/CLAUDE.md +1 -0
  55. package/bin/expand_home_directory_tokens.mjs +75 -0
  56. package/bin/install.mjs +21 -7
  57. package/bin/install.test.mjs +220 -10
  58. package/hooks/CLAUDE.md +1 -1
  59. package/hooks/blocking/CLAUDE.md +4 -1
  60. package/hooks/blocking/_path_setup.py +13 -0
  61. package/hooks/blocking/bash_pre_tool_use_dispatcher.py +281 -0
  62. package/hooks/blocking/code_rules_dead_module_constant.py +88 -16
  63. package/hooks/blocking/code_rules_enforcer.py +6 -0
  64. package/hooks/blocking/code_rules_imports_logging.py +34 -1
  65. package/hooks/blocking/code_rules_paths_syspath.py +1 -1
  66. package/hooks/blocking/code_rules_test_layout.py +272 -0
  67. package/hooks/blocking/nas_ssh_binary_enforcer.py +22 -12
  68. package/hooks/blocking/pii_prevention_blocker.py +781 -0
  69. package/hooks/blocking/pii_scanner.py +365 -0
  70. package/hooks/blocking/pre_tool_use_dispatcher.py +3 -3
  71. package/hooks/blocking/stop_dispatcher.py +84 -0
  72. package/hooks/blocking/test__path_setup.py +39 -0
  73. package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +61 -0
  74. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +294 -0
  75. package/hooks/blocking/test_code_rules_enforcer_cross_skill_duplicate.py +1 -1
  76. package/hooks/blocking/test_code_rules_enforcer_dead_config_field.py +2 -2
  77. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +51 -0
  78. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_read_cap.py +103 -0
  79. package/hooks/blocking/test_code_rules_enforcer_dot_test_pattern.py +1 -1
  80. package/hooks/blocking/test_code_rules_enforcer_file_global_constants.py +1 -1
  81. package/hooks/blocking/test_code_rules_enforcer_hardcoded_user_path.py +11 -11
  82. package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +1 -1
  83. package/hooks/blocking/test_code_rules_enforcer_same_file_inline_duplicate.py +1 -1
  84. package/hooks/blocking/test_code_rules_enforcer_test_layout.py +111 -0
  85. package/hooks/blocking/test_code_rules_enforcer_type_checking_scope.py +76 -0
  86. package/hooks/blocking/test_destructive_command_blocker.py +29 -9
  87. package/hooks/blocking/test_gh_body_arg_blocker.py +3 -3
  88. package/hooks/blocking/test_nas_ssh_binary_enforcer.py +96 -39
  89. package/hooks/blocking/test_pii_prevention_blocker.py +905 -0
  90. package/hooks/blocking/test_pii_prevention_windows_git_path.py +41 -0
  91. package/hooks/blocking/test_pii_scanner.py +190 -0
  92. package/hooks/blocking/test_pr_description_enforcer_pr_number.py +1 -1
  93. package/hooks/blocking/test_pre_tool_use_dispatcher.py +14 -13
  94. package/hooks/blocking/test_stop_dispatcher.py +187 -0
  95. package/hooks/blocking/test_verdict_directory_write_blocker.py +1 -1
  96. package/hooks/blocking/test_volatile_path_in_post_blocker.py +3 -3
  97. package/hooks/blocking/volatile_path_in_post_blocker.py +54 -5
  98. package/hooks/diagnostic/migrations/README.md +25 -26
  99. package/hooks/diagnostic/test_hook_log_extractor.py +10 -10
  100. package/hooks/hooks.json +10 -120
  101. package/hooks/hooks_constants/CLAUDE.md +12 -3
  102. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +78 -0
  103. package/hooks/hooks_constants/dead_module_constant_constants.py +1 -0
  104. package/hooks/hooks_constants/hosted_hook_runner.py +73 -0
  105. package/hooks/hooks_constants/local_identity.py +182 -0
  106. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +4 -37
  107. package/hooks/hooks_constants/pii_prevention_constants.py +295 -0
  108. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +4 -0
  109. package/hooks/hooks_constants/python_style_checks_constants.py +15 -0
  110. package/hooks/hooks_constants/stop_dispatcher_constants.py +26 -0
  111. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +87 -0
  112. package/hooks/hooks_constants/test_hardcoded_user_path_constants.py +2 -2
  113. package/hooks/hooks_constants/test_hosted_hook_runner.py +101 -0
  114. package/hooks/hooks_constants/test_layout_constants.py +28 -0
  115. package/hooks/hooks_constants/test_local_identity.py +88 -0
  116. package/hooks/hooks_constants/test_session_env_cleanup_constants.py +1 -1
  117. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +32 -0
  118. package/hooks/validators/README.md +5 -6
  119. package/hooks/validators/__init__.py +2 -2
  120. package/hooks/validators/python_style_checks.py +298 -243
  121. package/hooks/validators/run_all_validators.py +6 -0
  122. package/hooks/validators/test_python_style_checks.py +278 -163
  123. package/package.json +2 -2
  124. package/rules/CLAUDE.md +2 -1
  125. package/rules/bdd.md +1 -1
  126. package/rules/nas-ssh-invocation.md +6 -4
  127. package/rules/no-justification-noise.md +61 -0
  128. package/scripts/test_setup_project_paths.py +1 -1
  129. package/skills/CLAUDE.md +6 -3
  130. package/skills/_shared/pr-loop/scripts/_path_resolver.py +2 -2
  131. package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +1 -1
  132. package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +1 -1
  133. package/skills/_shared/pr-loop/scripts/test__path_resolver.py +42 -3
  134. package/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +11 -11
  135. package/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +26 -3
  136. package/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +49 -25
  137. package/skills/autoconverge/CLAUDE.md +3 -3
  138. package/skills/autoconverge/SKILL.md +113 -35
  139. package/skills/autoconverge/reference/CLAUDE.md +2 -2
  140. package/skills/autoconverge/reference/convergence.md +44 -22
  141. package/skills/autoconverge/reference/gotchas.md +11 -0
  142. package/skills/autoconverge/reference/stop-conditions.md +23 -13
  143. package/skills/autoconverge/workflow/CLAUDE.md +2 -1
  144. package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +15 -19
  145. package/skills/autoconverge/workflow/converge.contract.test.mjs +43 -42
  146. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +141 -16
  147. package/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +2 -2
  148. package/skills/autoconverge/workflow/converge.mjs +329 -68
  149. package/skills/autoconverge/workflow/converge.path-aware.test.mjs +1 -1
  150. package/skills/autoconverge/workflow/converge.precatch.test.mjs +152 -0
  151. package/skills/autoconverge/workflow/converge.run-input.test.mjs +3 -3
  152. package/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +15 -15
  153. package/skills/autoconverge/workflow/test_convergence_summary.py +6 -6
  154. package/skills/bdd-protocol/SKILL.md +4 -5
  155. package/skills/bdd-protocol/references/anti-patterns.md +1 -1
  156. package/skills/bugteam/SKILL.md +8 -0
  157. package/skills/bugteam/reference/copilot-gap-analysis.md +20 -20
  158. package/skills/bugteam/reference/obstacles/audit-walk-categories.md +1 -1
  159. package/skills/bugteam/reference/team-setup.md +7 -5
  160. package/skills/bugteam/scripts/reflow_skill_md.py +1 -1
  161. package/skills/copilot-finding-triage/SKILL.md +124 -0
  162. package/skills/copilot-finding-triage/reference/tier-rubric.md +49 -0
  163. package/skills/copilot-finding-triage/scripts/conftest.py +8 -0
  164. package/skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/__init__.py +0 -0
  165. package/skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/__init__.py +0 -0
  166. package/skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/notify_ntfy_constants.py +32 -0
  167. package/skills/copilot-finding-triage/scripts/notify_ntfy.py +192 -0
  168. package/skills/copilot-finding-triage/scripts/test_notify_ntfy.py +141 -0
  169. package/skills/copilot-finding-triage/templates/notification.md +34 -0
  170. package/skills/copilot-review/SKILL.md +8 -6
  171. package/skills/findbugs/SKILL.md +4 -0
  172. package/skills/fixbugs/SKILL.md +8 -7
  173. package/skills/gotcha/CLAUDE.md +2 -2
  174. package/skills/gotcha/SKILL.md +4 -4
  175. package/skills/log-audit/SKILL.md +4 -6
  176. package/skills/monitor-open-prs/CLAUDE.md +1 -1
  177. package/skills/monitor-open-prs/SKILL.md +6 -1
  178. package/skills/orchestrator/SKILL.md +74 -78
  179. package/skills/orchestrator-refresh/SKILL.md +24 -12
  180. package/skills/post-audit-findings/SKILL.md +5 -9
  181. package/skills/pr-consistency-audit/SKILL.md +5 -1
  182. package/skills/pr-converge/CLAUDE.md +1 -1
  183. package/skills/pr-converge/SKILL.md +86 -47
  184. package/skills/pr-converge/reference/CLAUDE.md +1 -1
  185. package/skills/pr-converge/reference/convergence-gates.md +20 -17
  186. package/skills/pr-converge/reference/examples.md +63 -47
  187. package/skills/pr-converge/reference/fix-protocol.md +15 -15
  188. package/skills/pr-converge/reference/ground-rules.md +11 -7
  189. package/skills/pr-converge/reference/multi-pr-orchestration.md +6 -5
  190. package/skills/pr-converge/reference/per-tick.md +129 -107
  191. package/skills/pr-converge/reference/state-schema.md +15 -10
  192. package/skills/pr-converge/scripts/check_convergence.py +5 -4
  193. package/skills/pr-converge/scripts/test_check_convergence.py +6 -4
  194. package/skills/pr-fix-protocol/SKILL.md +3 -8
  195. package/skills/pr-loop-cloud-transport/SKILL.md +102 -0
  196. package/skills/pr-loop-cloud-transport/reference/identity-and-hooks.md +40 -0
  197. package/skills/pr-loop-cloud-transport/reference/substitution-matrix.md +48 -0
  198. package/skills/pr-loop-lifecycle/SKILL.md +5 -9
  199. package/skills/pr-scope-resolve/SKILL.md +3 -6
  200. package/skills/privacy-hygiene/SKILL.md +114 -0
  201. package/skills/qbug/SKILL.md +8 -8
  202. package/skills/rebase/SKILL.md +5 -1
  203. package/skills/refine/SKILL.md +4 -5
  204. package/skills/reviewer-gates/SKILL.md +7 -11
  205. package/skills/session-log/SKILL.md +4 -1
  206. package/skills/skill-builder/SKILL.md +3 -6
  207. package/skills/structure-prompt/SKILL.md +4 -5
  208. package/skills/team-advisor/SKILL.md +56 -0
  209. package/skills/test_markdown_link_integrity.py +10 -6
  210. package/skills/update/SKILL.md +5 -1
  211. package/skills/usage-pause/SKILL.md +14 -5
  212. package/skills/usage-pause/scripts/resolve_usage_window.py +83 -5
  213. package/skills/usage-pause/scripts/test_resolve_usage_window.py +185 -17
  214. package/skills/usage-pause/scripts/usage_pause_constants/resolve_usage_window_constants.py +4 -3
  215. package/skills/verified-build/SKILL.md +4 -9
@@ -1,6 +1,6 @@
1
1
  # NAS SSH Invocation Policy
2
2
 
3
- **When this applies:** Any `ssh`, `scp`, or `sftp` command against the NAS at `192.168.1.100`.
3
+ **When this applies:** Any `ssh`, `scp`, or `sftp` command against the NAS.
4
4
 
5
5
  ## Rule
6
6
 
@@ -9,13 +9,15 @@ Reach the NAS through the Windows OpenSSH binary with batch mode on. Git Bash's
9
9
  Use this form for every NAS ssh command:
10
10
 
11
11
  ```
12
- "/c/Windows/System32/OpenSSH/ssh.exe" -o BatchMode=yes -o ConnectTimeout=10 -p 9222 jon@192.168.1.100 "<cmd>"
12
+ "/c/Windows/System32/OpenSSH/ssh.exe" -o BatchMode=yes -o ConnectTimeout=10 -p 22 operator@nas.example.local "<cmd>"
13
13
  ```
14
14
 
15
- `scp` and `sftp` take the matching `System32/OpenSSH` binary, `-o BatchMode=yes`, and port `9222` (`-P` for `scp`).
15
+ `scp` and `sftp` take the matching `System32/OpenSSH` binary, `-o BatchMode=yes`, and the same port (`-P` for `scp`).
16
+
17
+ The host, ssh user, and port come from the `CLAUDE_NAS_*` environment variables or `~/.claude/local-identity.json`; the committed examples show placeholders (`nas.example.local`, `operator`, `22`).
16
18
 
17
19
  `-o BatchMode=yes` is required, not optional: it turns a key-authentication failure into a loud non-zero exit rather than a silent password prompt, so an auth regression surfaces as an error you can read.
18
20
 
19
21
  ## Enforcement
20
22
 
21
- `nas_ssh_binary_enforcer.py` (PreToolUse on Bash) denies a bare `ssh`/`scp`/`sftp` command word aimed at `192.168.1.100` and points at the full-binary form. It also denies the full `System32/OpenSSH` binary to that host when the command omits `-o BatchMode=yes`. Commands to any other host, and commands that mention the address without an ssh-family command word, pass.
23
+ `nas_ssh_binary_enforcer.py` (PreToolUse on Bash) denies a bare `ssh`/`scp`/`sftp` command word aimed at the NAS host and points at the full-binary form. It also denies the full `System32/OpenSSH` binary to that host when the command omits `-o BatchMode=yes`. Commands to any other host, and commands that mention the address without an ssh-family command word, pass.
@@ -0,0 +1,61 @@
1
+ ---
2
+ paths:
3
+ - "**/*.md"
4
+ ---
5
+
6
+ # No Justification Noise in Documentation
7
+
8
+ **When this applies:** Any Write or Edit to a `.md` file.
9
+
10
+ ## Rule
11
+
12
+ Markdown states what the system is and does, in facts a reader can act on. Cut any sentence whose only job is to say why a choice is good, or to restate a gain the reader already works out from the stated behavior or from a rule a hook or another file enforces. A sentence like that carries no new fact — it repeats one the reader already holds, so it earns no space.
13
+
14
+ ## The test
15
+
16
+ For each sentence, ask: **does it state a fact the reader can act on that they could not already work out from the behavior around it or from a rule enforced elsewhere?** If no, cut the sentence.
17
+
18
+ ## Two shapes to catch
19
+
20
+ ### Pure noise — cut the whole sentence
21
+
22
+ A sentence whose only job is to point out a result that follows from a fact the doc already states.
23
+
24
+ > Autoconverge's bug-audit and self-review lenses and pr-converge's CODE_REVIEW step point at this file and read it when they run; they do not carry its text in their spawn prompts, so the checklist stays out of the per-round token budget.
25
+
26
+ The doc already states the lenses read the file. The "so it stays out of the token budget" tail is a result the reader works out alone, so it carries nothing. Cut the sentence.
27
+
28
+ ### Load-bearing first, noise after — keep the fact, cut the rest
29
+
30
+ A sentence that states a real fact, trailed by prose that only re-argues it or restates its payoff.
31
+
32
+ > The pre-catch stage drives the code to clean against these five lanes before any external reviewer sees it. External reviewers (Cursor Bugbot, GitHub Copilot) are terminal confirmation gates that run only after every lane below is clean, and they are expected to return zero findings.
33
+
34
+ Keep the first sentence — it states what the stage does. Cut the second: "run only after every lane below is clean" repeats the first sentence's claim, and "expected to return zero findings" is a hoped-for result, not a fact the reader acts on.
35
+
36
+ ## What stays
37
+
38
+ - A fact the reader acts on: an input a piece of code takes, an order a producer emits, a path a script writes.
39
+ - A rule's one-line reason stated in terms of present behavior — `--jq` runs per page, so cross-page sorts give wrong results — because that reason names a fact the reader needs to pick the right call.
40
+ - A tradeoff or a constraint the reader weighs before choosing a path.
41
+
42
+ ## Sibling rules
43
+
44
+ This rule sits beside three others; each cuts a different kind of dead prose.
45
+
46
+ | Rule | Cuts |
47
+ |---|---|
48
+ | `no-historical-clutter.md` | references to old state (`previously`, `migrated from`) |
49
+ | `self-contained-docs.md` | references to the chat that produced the doc |
50
+ | `plain-language.md` | heavy words with an everyday swap |
51
+ | `no-justification-noise.md` | a present-tense sentence that only justifies or restates a fact the reader already holds |
52
+
53
+ `no-historical-clutter.md` keeps a rule's reason when the reason names present behavior; this rule keeps the same reason for the same test. The two agree: a reason that names a fact the reader acts on stays, and a sentence that only re-argues a stated fact goes.
54
+
55
+ ## Enforcement
56
+
57
+ The AI review lane carries this rule: `AGENTS.md` names it as a finding an agent applies to the `.md` lines a PR changes. No hook backs it, because telling a justification sentence from a load-bearing one needs meaning a regex cannot read.
58
+
59
+ ## Why
60
+
61
+ A sentence that repeats a fact the reader already holds costs reading time and pays back nothing.
@@ -89,7 +89,7 @@ class TestExclusionFilter:
89
89
  assert filtered == []
90
90
 
91
91
  def test_drops_path_with_dot_cache_segment(self) -> None:
92
- all_candidates = ["C:\\Users\\jon\\.cache\\build"]
92
+ all_candidates = ["C:\\Users\\example\\.cache\\build"]
93
93
  filtered = setup.apply_exclusion_filter(all_candidates)
94
94
  assert filtered == []
95
95
 
package/skills/CLAUDE.md CHANGED
@@ -17,7 +17,7 @@ Skills install to `~/.claude/skills/<skill-name>/` via `packages/claude-dev-env/
17
17
 
18
18
  ## Shared support code
19
19
 
20
- `_shared/` — support code used by more than one skill. It holds `pr-loop/`, which provides prompt templates and Python helper scripts shared between `bugteam` and `pr-converge`.
20
+ `_shared/` — support code used by more than one skill. It holds `pr-loop/`, which provides prompt templates and Python helper scripts shared across the PR-loop skills, and `advisor/`, which provides the shared warm-advisor protocol used by `team-advisor` and `orchestrator`.
21
21
 
22
22
  ## Skill groups
23
23
 
@@ -26,8 +26,9 @@ Skills install to `~/.claude/skills/<skill-name>/` via `packages/claude-dev-env/
26
26
  - `implement` — structured implementation from an existing plan packet
27
27
  - `bdd-protocol` — BDD depth: Example Mapping, scenario quality, outside-in layout
28
28
  - `verified-build` — build + test loop that gates on a verifier verdict
29
- - `orchestrator` — turns the session into the advisor-orchestrator: it spawns executor subagents to do the code edits and test runs, and answers a blocked executor with a plan, correction, or stop
30
- - `orchestrator-refresh` — sub-skill fired by the `/orchestrator` loop to re-assert the executor-advisor discipline mid-run
29
+ - `orchestrator` — turns the session into the advisor-orchestrator: it spawns executor subagents to do the code edits and test runs; hard decisions go to a shared advisor (Claude warm `session-advisor` via SendMessage; Grok self-as-advisor on the orchestrating session)
30
+ - `orchestrator-refresh` — sub-skill fired by the `/orchestrator` loop to re-assert the host-matched shared-advisor discipline mid-run (Claude SendMessage; Grok self-as-advisor, no Agent spawn)
31
+ - `team-advisor` — binds one advisor at the strongest reachable tier (Claude warm agent; Grok self-as-advisor) and consults it for a second opinion before a big decision, at completion, when stuck, or when reconsidering the approach
31
32
 
32
33
  **PR review and convergence**
33
34
  - `autoconverge` — autonomous single-run workflow that drives a PR to ready
@@ -42,6 +43,7 @@ Skills install to `~/.claude/skills/<skill-name>/` via `packages/claude-dev-env/
42
43
  - `pr-fix-protocol` — fix, reply, and resolve reviewer findings; the unresolved-thread sweep
43
44
  - `post-audit-findings` — publishes an audit pass as one GitHub PR review
44
45
  - `pr-loop-lifecycle` — opens and closes a PR-loop run (grant, teardown, PR description, revoke, report)
46
+ - `pr-loop-cloud-transport` — six-step transport workflow that lets any PR-loop skill run in a session whose `gh` CLI is absent or cannot act on the PR (MCP schema load, origin/HEAD fix, identity rules, the gh-to-MCP substitution matrix, the Copilot status rule, and the post self-check)
45
47
  - `code` — strict-mode code generation session
46
48
 
47
49
  **Research and discovery**
@@ -57,6 +59,7 @@ Skills install to `~/.claude/skills/<skill-name>/` via `packages/claude-dev-env/
57
59
  - `session-tidy` — tidies the session folder
58
60
  - `bg-agent` — launches a background agent
59
61
  - `task-build` — gathers open tasks
62
+ - `privacy-hygiene` — full-repo personal-data and secret sweep plus remediation guide
60
63
  - `update` — updates the dev-env package
61
64
  - `gh-paginate` — safe `gh api` pagination patterns
62
65
  - `fresh-branch` — creates a clean branch off main
@@ -98,7 +98,7 @@ def slugify_pr_identity(owner: str, repo: str, pr_number: int) -> str:
98
98
  pr_number: Pull request number.
99
99
 
100
100
  Returns:
101
- Slugified token (e.g. 'jl-cmd-claude-code-config-pr-422').
101
+ Slugified token (e.g. 'jl-cmd-claude-dev-env-pr-422').
102
102
  """
103
103
  return MULTI_PR_SLUG_TEMPLATE.format(owner=owner, repo=repo, number=pr_number)
104
104
 
@@ -179,7 +179,7 @@ def diff_patch_path(
179
179
  loop_number: Current loop iteration.
180
180
 
181
181
  Returns:
182
- Absolute path (e.g. '<run_temp>/jl-cmd-claude-code-config-pr-422/loop-3.patch').
182
+ Absolute path (e.g. '<run_temp>/jl-cmd-claude-dev-env-pr-422/loop-3.patch').
183
183
  """
184
184
  slug = slugify_pr_identity(owner, repo, pr_number)
185
185
  filename = DIFF_PATCH_TEMPLATE.format(loop=loop_number)
@@ -7,7 +7,7 @@ inline. <pr_description> carries the PR body text read from --pr-body-file,
7
7
  and stays empty when that argument is absent or the file cannot be read.
8
8
 
9
9
  Usage:
10
- python scripts/build_audit_prompt.py --owner jl-cmd --repo claude-code-config --pr-number 422 --loop 1 --head-ref feat/branch --base-ref main --worktree-path <PATH> --run-temp-dir <PATH>
10
+ python scripts/build_audit_prompt.py --owner jl-cmd --repo claude-dev-env --pr-number 422 --loop 1 --head-ref feat/branch --base-ref main --worktree-path <PATH> --run-temp-dir <PATH>
11
11
  """
12
12
 
13
13
  from __future__ import annotations
@@ -4,7 +4,7 @@ Populates <bug> entries from findings JSON, plus <execution> checklist
4
4
  and <constraints>.
5
5
 
6
6
  Usage:
7
- python scripts/build_fix_prompt.py --owner jl-cmd --repo claude-code-config --pr-number 422 --loop 1 --head-ref feat/branch --base-ref main --worktree-path <PATH> --findings-json <PATH>
7
+ python scripts/build_fix_prompt.py --owner jl-cmd --repo claude-dev-env --pr-number 422 --loop 1 --head-ref feat/branch --base-ref main --worktree-path <PATH> --findings-json <PATH>
8
8
  """
9
9
 
10
10
  from __future__ import annotations
@@ -32,7 +32,7 @@ path_resolver = _load_path_resolver()
32
32
  def test_per_pr_workspace_returns_typed_structure_with_concrete_fields() -> None:
33
33
  run_temp_dir = Path("/tmp/bugteam-pr-422")
34
34
  workspace = path_resolver.per_pr_workspace(
35
- run_temp_dir, "jl-cmd", "claude-code-config", 422
35
+ run_temp_dir, "jl-cmd", "claude-dev-env", 422
36
36
  )
37
37
  assert isinstance(workspace, path_resolver.PerPrWorkspace)
38
38
  assert isinstance(workspace.worktree, Path)
@@ -51,11 +51,11 @@ def test_per_pr_workspace_diff_patch_template_carries_loop_placeholder() -> None
51
51
 
52
52
 
53
53
  def test_per_pr_workspace_diff_patch_template_uses_forward_slashes() -> None:
54
- run_temp_dir = Path("C:/Users/jon/AppData/Local/Temp/bugteam-pr-376")
54
+ run_temp_dir = Path("C:/Users/example/AppData/Local/Temp/bugteam-pr-376")
55
55
  workspace = path_resolver.per_pr_workspace(run_temp_dir, "owner", "repo", 376)
56
56
  assert "\\" not in workspace.diff_patch_template
57
57
  assert workspace.diff_patch_template == (
58
- "C:/Users/jon/AppData/Local/Temp/bugteam-pr-376/"
58
+ "C:/Users/example/AppData/Local/Temp/bugteam-pr-376/"
59
59
  "pr-376/owner-repo-pr-376/loop-{loop}.patch"
60
60
  )
61
61
 
@@ -65,3 +65,42 @@ def test_per_pr_workspace_is_frozen() -> None:
65
65
  workspace = path_resolver.per_pr_workspace(run_temp_dir, "owner", "repo", 9)
66
66
  with pytest.raises(dataclasses.FrozenInstanceError):
67
67
  workspace.worktree = Path("/tmp/other")
68
+
69
+
70
+ def test_sanitize_branch_name_replaces_filesystem_unsafe_characters() -> None:
71
+ assert path_resolver.sanitize_branch_name("feat/my-branch") == "feat-my-branch"
72
+
73
+
74
+ def test_build_run_name_uses_pr_number_for_single_pr() -> None:
75
+ assert path_resolver.build_run_name(422, "feat/x", is_multi_pr=False) == "bugteam-pr-422"
76
+
77
+
78
+ def test_build_run_name_uses_sanitized_branch_for_multi_pr() -> None:
79
+ assert path_resolver.build_run_name(422, "feat/x", is_multi_pr=True) == "bugteam-feat-x"
80
+
81
+
82
+ def test_slugify_pr_identity_joins_owner_repo_and_number() -> None:
83
+ assert (
84
+ path_resolver.slugify_pr_identity("jl-cmd", "claude-dev-env", 422)
85
+ == "jl-cmd-claude-dev-env-pr-422"
86
+ )
87
+
88
+
89
+ def test_outcome_xml_path_embeds_pr_and_loop() -> None:
90
+ worktree_path = Path("/tmp/worktree")
91
+ outcome_path = path_resolver.outcome_xml_path(worktree_path, 422, 3)
92
+ assert outcome_path == worktree_path / ".bugteam-pr422-loop3.outcomes.xml"
93
+
94
+
95
+ def test_fix_outcome_xml_path_embeds_pr_and_loop() -> None:
96
+ worktree_path = Path("/tmp/worktree")
97
+ fix_outcome_path = path_resolver.fix_outcome_xml_path(worktree_path, 422, 3)
98
+ assert fix_outcome_path == worktree_path / ".bugteam-pr422-loop3.fix-outcomes.xml"
99
+
100
+
101
+ def test_diff_patch_path_joins_slug_and_loop_filename() -> None:
102
+ run_temp_dir = Path("/tmp/run")
103
+ patch_path = path_resolver.diff_patch_path(
104
+ run_temp_dir, "owner", "repo", 7, 2
105
+ )
106
+ assert patch_path == run_temp_dir / "owner-repo-pr-7" / "loop-2.patch"
@@ -50,7 +50,7 @@ def _rubric_label_by_letter() -> dict[str, str]:
50
50
  def _build_audit_root() -> Element:
51
51
  return build_audit_prompt.build_audit_prompt_xml(
52
52
  owner="jl-cmd",
53
- repo="claude-code-config",
53
+ repo="claude-dev-env",
54
54
  pr_number=422,
55
55
  loop=1,
56
56
  head_ref="feat/branch",
@@ -63,25 +63,25 @@ def _build_audit_root() -> Element:
63
63
  def test_context_and_scope_render_paths_with_forward_slashes() -> None:
64
64
  root = build_audit_prompt.build_audit_prompt_xml(
65
65
  owner="jl-cmd",
66
- repo="claude-code-config",
66
+ repo="claude-dev-env",
67
67
  pr_number=376,
68
68
  loop=1,
69
69
  head_ref="feat/branch",
70
70
  base_ref="main",
71
- worktree_path=Path("C:/Users/jon/AppData/Local/Temp/bugteam-pr-376/worktree"),
72
- run_temp_dir=Path("C:/Users/jon/AppData/Local/Temp/bugteam-pr-376"),
71
+ worktree_path=Path("C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree"),
72
+ run_temp_dir=Path("C:/Users/example/AppData/Local/Temp/bugteam-pr-376"),
73
73
  )
74
74
  context = root.find("context")
75
75
  assert context is not None
76
76
  worktree_text = context.findtext("worktree_path")
77
77
  run_temp_text = context.findtext("run_temp_dir")
78
- assert worktree_text == "C:/Users/jon/AppData/Local/Temp/bugteam-pr-376/worktree"
79
- assert run_temp_text == "C:/Users/jon/AppData/Local/Temp/bugteam-pr-376"
78
+ assert worktree_text == "C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree"
79
+ assert run_temp_text == "C:/Users/example/AppData/Local/Temp/bugteam-pr-376"
80
80
  scope = root.find("scope")
81
81
  assert scope is not None
82
82
  assert scope.text is not None
83
83
  assert "\\" not in scope.text
84
- assert "C:/Users/jon/AppData/Local/Temp/bugteam-pr-376/worktree" in scope.text
84
+ assert "C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree" in scope.text
85
85
 
86
86
 
87
87
  def test_bug_categories_carry_ids_a_through_q_in_order() -> None:
@@ -179,7 +179,7 @@ def test_bug_categories_include_category_q() -> None:
179
179
  def test_pr_description_carries_body_text_when_supplied() -> None:
180
180
  root = build_audit_prompt.build_audit_prompt_xml(
181
181
  owner="jl-cmd",
182
- repo="claude-code-config",
182
+ repo="claude-dev-env",
183
183
  pr_number=422,
184
184
  loop=1,
185
185
  head_ref="feat/branch",
@@ -218,7 +218,7 @@ def test_read_pr_body_text_returns_none_when_file_missing(tmp_path: Path) -> Non
218
218
  def test_emit_audit_prompt_embeds_pr_body_text_in_pr_description() -> None:
219
219
  xml_text = build_audit_prompt.emit_audit_prompt(
220
220
  owner="jl-cmd",
221
- repo="claude-code-config",
221
+ repo="claude-dev-env",
222
222
  pr_number=422,
223
223
  loop=1,
224
224
  head_ref="feat/branch",
@@ -233,7 +233,7 @@ def test_emit_audit_prompt_embeds_pr_body_text_in_pr_description() -> None:
233
233
  def test_parse_arguments_defaults_pr_body_file_to_none() -> None:
234
234
  arguments = build_audit_prompt.parse_arguments([
235
235
  "--owner", "jl-cmd",
236
- "--repo", "claude-code-config",
236
+ "--repo", "claude-dev-env",
237
237
  "--pr-number", "422",
238
238
  "--loop", "1",
239
239
  "--head-ref", "feat/branch",
@@ -247,7 +247,7 @@ def test_parse_arguments_defaults_pr_body_file_to_none() -> None:
247
247
  def test_parse_arguments_reads_pr_body_file_path() -> None:
248
248
  arguments = build_audit_prompt.parse_arguments([
249
249
  "--owner", "jl-cmd",
250
- "--repo", "claude-code-config",
250
+ "--repo", "claude-dev-env",
251
251
  "--pr-number", "422",
252
252
  "--loop", "1",
253
253
  "--head-ref", "feat/branch",
@@ -35,15 +35,38 @@ def test_context_worktree_path_renders_with_forward_slashes(tmp_path: Path) -> N
35
35
  )
36
36
  root = build_fix_prompt.build_fix_prompt_xml(
37
37
  owner="jl-cmd",
38
- repo="claude-code-config",
38
+ repo="claude-dev-env",
39
39
  pr_number=376,
40
40
  loop=1,
41
41
  head_ref="feat/branch",
42
42
  base_ref="main",
43
- worktree_path=Path("C:/Users/jon/AppData/Local/Temp/bugteam-pr-376/worktree"),
43
+ worktree_path=Path("C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree"),
44
44
  findings_json_path=findings_json_path,
45
45
  )
46
46
  context = root.find("context")
47
47
  assert context is not None
48
48
  worktree_text = context.findtext("worktree_path")
49
- assert worktree_text == "C:/Users/jon/AppData/Local/Temp/bugteam-pr-376/worktree"
49
+ assert worktree_text == "C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree"
50
+
51
+
52
+ def test_emit_fix_prompt_returns_xml_string_with_worktree_path(tmp_path: Path) -> None:
53
+ findings_json_path = tmp_path / "findings.json"
54
+ findings_json_path.write_text(
55
+ json.dumps([{"severity": "P1", "file": "a.py", "line": 1}]),
56
+ encoding="utf-8",
57
+ )
58
+ worktree_path = Path("C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree")
59
+ xml_text = build_fix_prompt.emit_fix_prompt(
60
+ owner="jl-cmd",
61
+ repo="claude-dev-env",
62
+ pr_number=376,
63
+ loop=1,
64
+ head_ref="feat/branch",
65
+ base_ref="main",
66
+ worktree_path=worktree_path,
67
+ findings_json_path=findings_json_path,
68
+ )
69
+ assert isinstance(xml_text, str)
70
+ assert "C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree" in xml_text
71
+ assert 'role="fix"' in xml_text
72
+ assert "<spawn_prompt" in xml_text
@@ -29,7 +29,7 @@ def _load_preflight() -> ModuleType:
29
29
  preflight = _load_preflight()
30
30
 
31
31
  GIT_TIMEOUT = 30
32
- CLAUDE_REMOTE = "https://github.com/jl-cmd/claude-code-config.git"
32
+ CLAUDE_REMOTE = "https://github.com/jl-cmd/claude-dev-env.git"
33
33
  GIT_CEILING_DIRECTORIES = "GIT_CEILING_DIRECTORIES"
34
34
 
35
35
 
@@ -68,20 +68,20 @@ def _init_repo(repo_dir: Path, origin_url: str | None) -> Path:
68
68
  ("remote_url", "expected_owner", "expected_repo"),
69
69
  [
70
70
  (
71
- "https://github.com/jl-cmd/claude-code-config.git",
71
+ "https://github.com/jl-cmd/claude-dev-env.git",
72
72
  "jl-cmd",
73
- "claude-code-config",
73
+ "claude-dev-env",
74
74
  ),
75
75
  (
76
- "https://github.com/jl-cmd/claude-code-config",
76
+ "https://github.com/jl-cmd/claude-dev-env",
77
77
  "jl-cmd",
78
- "claude-code-config",
78
+ "claude-dev-env",
79
79
  ),
80
- ("git@github.com:JonEcho/llm-settings.git", "jonecho", "llm-settings"),
80
+ ("git@github.com:Example/llm-settings.git", "example", "llm-settings"),
81
81
  (
82
- "ssh://git@github.com/jl-cmd/Claude-Code-Config",
82
+ "ssh://git@github.com/jl-cmd/Claude-Dev-Env",
83
83
  "jl-cmd",
84
- "claude-code-config",
84
+ "claude-dev-env",
85
85
  ),
86
86
  ("https://github.com/jl-cmd/repo/", "jl-cmd", "repo"),
87
87
  ],
@@ -103,9 +103,33 @@ def test_parse_repo_identity_rejects_non_github_remotes(remote_url: str) -> None
103
103
  assert preflight.parse_repo_identity(remote_url) is None
104
104
 
105
105
 
106
+ def test_is_inside_work_tree_true_in_git_repo(tmp_path: Path) -> None:
107
+ repo_dir = _init_repo(tmp_path / "session", None)
108
+ assert preflight.is_inside_work_tree(repo_dir) is True
109
+
110
+
111
+ def test_is_inside_work_tree_false_in_plain_directory(tmp_path: Path) -> None:
112
+ plain_dir = tmp_path / "home"
113
+ plain_dir.mkdir()
114
+ assert preflight.is_inside_work_tree(plain_dir) is False
115
+
116
+
117
+ def test_worktree_machinery_is_healthy_true_in_git_repo(tmp_path: Path) -> None:
118
+ repo_dir = _init_repo(tmp_path / "session", None)
119
+ assert preflight.worktree_machinery_is_healthy(repo_dir) is True
120
+
121
+
122
+ def test_worktree_machinery_is_healthy_false_in_plain_directory(
123
+ tmp_path: Path,
124
+ ) -> None:
125
+ plain_dir = tmp_path / "home"
126
+ plain_dir.mkdir()
127
+ assert preflight.worktree_machinery_is_healthy(plain_dir) is False
128
+
129
+
106
130
  def test_classify_same_repo_when_origin_matches_pr(tmp_path: Path) -> None:
107
131
  repo_dir = _init_repo(tmp_path / "session", CLAUDE_REMOTE)
108
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-code-config")
132
+ pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
109
133
  verdict = preflight.classify_environment(repo_dir, pr_identity)
110
134
  assert verdict.outcome == preflight.OUTCOME_SAME_REPO
111
135
  assert verdict.cwd_identity == pr_identity
@@ -116,17 +140,17 @@ def test_classify_different_repo_when_origin_is_another_github_repo(
116
140
  tmp_path: Path,
117
141
  ) -> None:
118
142
  repo_dir = _init_repo(
119
- tmp_path / "session", "https://github.com/jonecho/llm-settings.git"
143
+ tmp_path / "session", "https://github.com/example/llm-settings.git"
120
144
  )
121
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-code-config")
145
+ pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
122
146
  verdict = preflight.classify_environment(repo_dir, pr_identity)
123
147
  assert verdict.outcome == preflight.OUTCOME_DIFFERENT_REPO
124
- assert verdict.cwd_identity == preflight.RepoIdentity("jonecho", "llm-settings")
148
+ assert verdict.cwd_identity == preflight.RepoIdentity("example", "llm-settings")
125
149
 
126
150
 
127
151
  def test_classify_different_repo_when_origin_is_non_github(tmp_path: Path) -> None:
128
152
  repo_dir = _init_repo(tmp_path / "session", "https://gitlab.com/foo/bar.git")
129
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-code-config")
153
+ pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
130
154
  verdict = preflight.classify_environment(repo_dir, pr_identity)
131
155
  assert verdict.outcome == preflight.OUTCOME_DIFFERENT_REPO
132
156
  assert verdict.cwd_identity is None
@@ -134,7 +158,7 @@ def test_classify_different_repo_when_origin_is_non_github(tmp_path: Path) -> No
134
158
 
135
159
  def test_classify_re_rooted_when_origin_is_absent(tmp_path: Path) -> None:
136
160
  repo_dir = _init_repo(tmp_path / "session", None)
137
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-code-config")
161
+ pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
138
162
  verdict = preflight.classify_environment(repo_dir, pr_identity)
139
163
  assert verdict.outcome == preflight.OUTCOME_RE_ROOTED
140
164
 
@@ -144,7 +168,7 @@ def test_classify_re_rooted_when_directory_is_not_a_work_tree(
144
168
  ) -> None:
145
169
  plain_dir = tmp_path / "home"
146
170
  plain_dir.mkdir()
147
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-code-config")
171
+ pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
148
172
  verdict = preflight.classify_environment(plain_dir, pr_identity)
149
173
  assert verdict.outcome == preflight.OUTCOME_RE_ROOTED
150
174
  assert verdict.has_healthy_worktree_machinery is False
@@ -177,10 +201,10 @@ def test_decide_exit_code_matrix(
177
201
  def test_build_report_lines_marks_outcome_and_routes_cross_repo() -> None:
178
202
  verdict = preflight.PreflightVerdict(
179
203
  outcome=preflight.OUTCOME_DIFFERENT_REPO,
180
- cwd_identity=preflight.RepoIdentity("jonecho", "llm-settings"),
204
+ cwd_identity=preflight.RepoIdentity("example", "llm-settings"),
181
205
  has_healthy_worktree_machinery=True,
182
206
  )
183
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-code-config")
207
+ pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
184
208
  classify_lines = preflight.build_report_lines(
185
209
  verdict, "classify", Path("/tmp/x"), pr_identity
186
210
  )
@@ -195,10 +219,10 @@ def test_build_report_lines_marks_outcome_and_routes_cross_repo() -> None:
195
219
  def test_build_report_lines_aborts_on_broken_worktree_machinery() -> None:
196
220
  verdict = preflight.PreflightVerdict(
197
221
  outcome=preflight.OUTCOME_SAME_REPO,
198
- cwd_identity=preflight.RepoIdentity("jl-cmd", "claude-code-config"),
222
+ cwd_identity=preflight.RepoIdentity("jl-cmd", "claude-dev-env"),
199
223
  has_healthy_worktree_machinery=False,
200
224
  )
201
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-code-config")
225
+ pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
202
226
  lines = preflight.build_report_lines(verdict, "strict", Path("/tmp/x"), pr_identity)
203
227
  assert lines[0] == "PREFLIGHT_OUTCOME=same_repo"
204
228
  assert any("git worktree prune" in line for line in lines)
@@ -210,7 +234,7 @@ def test_main_strict_passes_in_matching_repo(
210
234
  repo_dir = _init_repo(tmp_path / "session", CLAUDE_REMOTE)
211
235
  monkeypatch.chdir(repo_dir)
212
236
  exit_code = preflight.main(
213
- ["--owner", "jl-cmd", "--repo", "claude-code-config", "--mode", "strict"]
237
+ ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "strict"]
214
238
  )
215
239
  captured = capsys.readouterr()
216
240
  assert exit_code == preflight.EXIT_PREFLIGHT_OK
@@ -221,11 +245,11 @@ def test_main_strict_aborts_when_session_rooted_in_other_repo(
221
245
  tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
222
246
  ) -> None:
223
247
  repo_dir = _init_repo(
224
- tmp_path / "session", "https://github.com/jonecho/llm-settings.git"
248
+ tmp_path / "session", "https://github.com/example/llm-settings.git"
225
249
  )
226
250
  monkeypatch.chdir(repo_dir)
227
251
  exit_code = preflight.main(
228
- ["--owner", "jl-cmd", "--repo", "claude-code-config", "--mode", "strict"]
252
+ ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "strict"]
229
253
  )
230
254
  captured = capsys.readouterr()
231
255
  assert exit_code == preflight.EXIT_PREFLIGHT_ABORT
@@ -237,11 +261,11 @@ def test_main_classify_routes_cross_repo_without_abort(
237
261
  tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
238
262
  ) -> None:
239
263
  repo_dir = _init_repo(
240
- tmp_path / "session", "https://github.com/jonecho/llm-settings.git"
264
+ tmp_path / "session", "https://github.com/example/llm-settings.git"
241
265
  )
242
266
  monkeypatch.chdir(repo_dir)
243
267
  exit_code = preflight.main(
244
- ["--owner", "jl-cmd", "--repo", "claude-code-config", "--mode", "classify"]
268
+ ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "classify"]
245
269
  )
246
270
  captured = capsys.readouterr()
247
271
  assert exit_code == preflight.EXIT_PREFLIGHT_OK
@@ -256,7 +280,7 @@ def test_main_classify_aborts_when_re_rooted(
256
280
  plain_dir.mkdir()
257
281
  monkeypatch.chdir(plain_dir)
258
282
  exit_code = preflight.main(
259
- ["--owner", "jl-cmd", "--repo", "claude-code-config", "--mode", "classify"]
283
+ ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "classify"]
260
284
  )
261
285
  captured = capsys.readouterr()
262
286
  assert exit_code == preflight.EXIT_PREFLIGHT_ABORT
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Trigger:** `/autoconverge`, "autoconverge this PR", "converge this PR in one run", "run the converge workflow", "drive the PR to ready autonomously".
4
4
 
5
- Drives one draft PR to convergence in a single autonomous workflow run. Each round runs Cursor Bugbot, a code-review pass, and a bug-audit in parallel on the same HEAD, deduplicates findings, applies every fix in one commit, re-verifies, clears a Copilot wait-gate, and marks the PR ready on convergence. State lives in the workflow journal; no `ScheduleWakeup` ticks.
5
+ Drives one draft PR to convergence in a single autonomous workflow run. Each round runs a deterministic static sweep first, then a code-review pass, a bug-audit (with its adversarial second pass), and a self-review parity pass in parallel on the same HEAD, deduplicates findings, applies every fix in one commit, and re-verifies. Once the internal lenses are clean, Cursor Bugbot and Copilot run as terminal confirmation gates, and the run marks the PR ready on convergence. State lives in the workflow journal; no `ScheduleWakeup` ticks.
6
6
 
7
7
  ## Subdirectories
8
8
 
@@ -16,11 +16,11 @@ Drives one draft PR to convergence in a single autonomous workflow run. Each rou
16
16
  | File | Role |
17
17
  |---|---|
18
18
  | `SKILL.md` | Full entry-point protocol: pre-flight steps, worktree setup, `Workflow` call, budget-aware round boundaries, teardown, and the per-round convergence loop summary. |
19
- | `workflow/converge.mjs` | Main convergence workflow. Runs rounds, gates on Copilot, checks convergence, and marks the PR ready. |
19
+ | `workflow/converge.mjs` | Main convergence workflow. Runs a static sweep then the internal lenses each round, applies fixes, runs Bugbot and Copilot as terminal gates, checks convergence, and marks the PR ready. |
20
20
  | `workflow/aggregate_runs.py` | Merges every autoconverge journal for a PR into one deduped journal. |
21
21
  | `workflow/convergence_summary.py` | Builds the convergence-summary agent prompt over the merged findings. |
22
22
  | `workflow/render_report.py` | Builds the closing HTML report from the merged journal and summary. |
23
- | `reference/convergence.md` | Round shape: the three parallel lenses, deduplication, fix commit, and the ready definition. |
23
+ | `reference/convergence.md` | Round shape: the static sweep, the three parallel internal lenses, deduplication, fix commit, the terminal Bugbot and Copilot gates, and the ready definition. |
24
24
  | `reference/stop-conditions.md` | Every way the run ends short of ready. |
25
25
  | `reference/gotchas.md` | Hard-won failure lessons. |
26
26
  | `reference/closing-report.md` | Specification for the closing HTML report format. |