claude-dev-env 1.93.1 → 1.95.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 (262) hide show
  1. package/_shared/advisor/CLAUDE.md +2 -2
  2. package/_shared/advisor/advisor-protocol.md +35 -27
  3. package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +3 -2
  4. package/_shared/advisor/scripts/model_tier_run_validator.py +23 -15
  5. package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +81 -17
  6. package/_shared/pr-loop/CLAUDE.md +1 -0
  7. package/_shared/pr-loop/audit-contract.md +1 -1
  8. package/_shared/pr-loop/gh-payloads.md +3 -3
  9. package/_shared/pr-loop/post-audit-thread-contract.md +51 -0
  10. package/_shared/pr-loop/scripts/README.md +2 -2
  11. package/_shared/pr-loop/scripts/fix_hookspath.py +47 -12
  12. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -69
  13. package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -374
  14. package/_shared/pr-loop/state-schema.md +3 -22
  15. package/bin/CLAUDE.md +11 -2
  16. package/bin/ever-shipped-skills.mjs +70 -0
  17. package/bin/install.mjs +138 -13
  18. package/bin/install.prune.test.mjs +457 -0
  19. package/bin/install.test.mjs +10 -4
  20. package/docs/CODE_RULES.md +1 -1
  21. package/hooks/blocking/CLAUDE.md +2 -0
  22. package/hooks/blocking/code_rules_enforcer.py +4 -0
  23. package/hooks/blocking/code_rules_shared.py +82 -0
  24. package/hooks/blocking/code_rules_test_layout.py +9 -3
  25. package/hooks/blocking/pii_commit_command.py +398 -0
  26. package/hooks/blocking/pii_payload_scan.py +133 -0
  27. package/hooks/blocking/pii_prevention_blocker.py +151 -449
  28. package/hooks/blocking/plain_language_blocker.py +138 -4
  29. package/hooks/blocking/sensitive_file_protector.py +114 -48
  30. package/hooks/blocking/tdd_enforcer.py +9 -2
  31. package/hooks/blocking/test_code_rules_enforcer_scratchpad.py +105 -0
  32. package/hooks/blocking/test_code_rules_shared.py +181 -0
  33. package/hooks/blocking/test_pii_prevention_blocker.py +299 -0
  34. package/hooks/blocking/test_plain_language_blocker_allowlist.py +184 -0
  35. package/hooks/blocking/test_sensitive_file_protector.py +185 -0
  36. package/hooks/blocking/test_tdd_enforcer_scratchpad.py +105 -0
  37. package/hooks/blocking/test_verdict_directory_write_blocker.py +42 -7
  38. package/hooks/hooks_constants/CLAUDE.md +4 -2
  39. package/hooks/hooks_constants/code_rules_path_utils_constants.py +0 -2
  40. package/hooks/hooks_constants/harness_scratchpad_constants.py +17 -0
  41. package/hooks/hooks_constants/local_identity.py +65 -15
  42. package/hooks/hooks_constants/pii_prevention_constants.py +16 -0
  43. package/hooks/hooks_constants/plain_language_blocker_constants.py +5 -0
  44. package/hooks/hooks_constants/pr_description_enforcer_constants.py +1 -1
  45. package/hooks/hooks_constants/sensitive_file_protector_constants.py +42 -0
  46. package/hooks/hooks_constants/test_local_identity.py +68 -0
  47. package/hooks/pyproject.toml +75 -4
  48. package/hooks/validators/CLAUDE.md +1 -1
  49. package/hooks/validators/README.md +2 -0
  50. package/hooks/validators/python_style_checks.py +114 -136
  51. package/hooks/validators/python_style_helpers.py +95 -0
  52. package/hooks/validators/test_python_style_checks.py +0 -164
  53. package/hooks/validators/test_python_style_checks_decorator_gap.py +119 -0
  54. package/hooks/validators/test_python_style_fixes.py +251 -0
  55. package/hooks/validators/test_python_style_helpers.py +125 -0
  56. package/package.json +1 -1
  57. package/rules/CLAUDE.md +1 -0
  58. package/rules/anti-corollary-tests.md +69 -0
  59. package/rules/bdd.md +1 -3
  60. package/rules/code-reviews.md +1 -1
  61. package/rules/gh-paginate.md +1 -1
  62. package/rules/plain-language.md +2 -0
  63. package/scripts/CLAUDE.md +10 -1
  64. package/scripts/Get-SessionAccount.ps1 +210 -0
  65. package/scripts/tests/CLAUDE.md +15 -1
  66. package/scripts/tests/Get-SessionAccount.Tests.ps1 +350 -0
  67. package/skills/CLAUDE.md +6 -27
  68. package/skills/anthropic-plan/SKILL.md +1 -13
  69. package/skills/autoconverge/CLAUDE.md +5 -2
  70. package/skills/autoconverge/SKILL.md +112 -387
  71. package/skills/autoconverge/reference/CLAUDE.md +4 -1
  72. package/skills/autoconverge/reference/closing-report.md +9 -2
  73. package/skills/autoconverge/reference/convergence.md +26 -22
  74. package/skills/autoconverge/reference/headless-safety.md +44 -0
  75. package/skills/autoconverge/reference/multi-pr.md +88 -0
  76. package/skills/autoconverge/reference/self-closing-loop.md +84 -0
  77. package/skills/autoconverge/reference/stop-conditions.md +21 -13
  78. package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +87 -27
  79. package/skills/autoconverge/workflow/converge.contract.test.mjs +40 -10
  80. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +179 -47
  81. package/skills/autoconverge/workflow/converge.fix-progress.test.mjs +1 -1
  82. package/skills/autoconverge/workflow/converge.mjs +286 -96
  83. package/skills/bugteam/CLAUDE.md +1 -1
  84. package/skills/bugteam/CONSTRAINTS.md +3 -3
  85. package/skills/bugteam/PROMPTS.md +8 -19
  86. package/skills/bugteam/SKILL.md +13 -14
  87. package/skills/bugteam/reference/CLAUDE.md +1 -1
  88. package/skills/bugteam/reference/README.md +2 -3
  89. package/skills/bugteam/reference/audit-and-teammates.md +2 -2
  90. package/skills/bugteam/reference/copilot-gap-analysis.md +2 -0
  91. package/skills/bugteam/reference/github-pr-reviews.md +56 -38
  92. package/skills/bugteam/reference/team-setup.md +11 -11
  93. package/skills/bugteam/scripts/CLAUDE.md +6 -6
  94. package/skills/bugteam/scripts/README.md +20 -8
  95. package/skills/bugteam/scripts/bugteam_code_rules_gate.py +13 -1463
  96. package/skills/bugteam/scripts/bugteam_fix_hookspath.py +23 -358
  97. package/skills/bugteam/scripts/bugteam_preflight.py +13 -315
  98. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +2 -3
  99. package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +34 -1053
  100. package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +30 -347
  101. package/skills/bugteam/scripts/test_bugteam_preflight.py +30 -305
  102. package/skills/closeout/SKILL.md +153 -0
  103. package/skills/closeout/reference/handoff-prompt-template.md +72 -0
  104. package/skills/closeout/reference/issue-body-templates.md +108 -0
  105. package/skills/closeout/reference/pii-redaction-checklist.md +36 -0
  106. package/skills/copilot-finding-triage/SKILL.md +80 -28
  107. package/skills/copilot-finding-triage/reference/tier-rubric.md +70 -11
  108. package/skills/copilot-finding-triage/templates/notification.md +8 -3
  109. package/skills/everything-search/SKILL.md +1 -2
  110. package/skills/grokify/SKILL.md +58 -0
  111. package/skills/grokify/templates/handoff-template.md +92 -0
  112. package/skills/orchestrator/SKILL.md +35 -25
  113. package/skills/orchestrator-refresh/SKILL.md +15 -11
  114. package/skills/pr-converge/CLAUDE.md +1 -1
  115. package/skills/pr-converge/SKILL.md +132 -233
  116. package/skills/pr-converge/reference/convergence-gates.md +102 -66
  117. package/skills/pr-converge/reference/examples.md +37 -25
  118. package/skills/pr-converge/reference/fix-protocol.md +7 -7
  119. package/skills/pr-converge/reference/multi-pr-orchestration.md +10 -4
  120. package/skills/pr-converge/reference/per-tick.md +64 -41
  121. package/skills/pr-converge/reference/state-schema.md +27 -2
  122. package/skills/pr-converge/scripts/CLAUDE.md +8 -0
  123. package/skills/pr-converge/scripts/README.md +4 -3
  124. package/skills/pr-converge/scripts/_pr_converge_path_setup.py +23 -0
  125. package/skills/pr-converge/scripts/check_convergence.py +189 -645
  126. package/skills/pr-converge/scripts/check_convergence_gates.py +235 -0
  127. package/skills/pr-converge/scripts/check_convergence_thread_gates.py +219 -0
  128. package/skills/pr-converge/scripts/conftest.py +8 -0
  129. package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +1 -0
  130. package/skills/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +36 -0
  131. package/skills/pr-converge/scripts/test__pr_converge_path_setup.py +26 -0
  132. package/skills/pr-converge/scripts/test_check_convergence.py +73 -228
  133. package/skills/pr-converge/scripts/test_check_convergence_contract.py +321 -0
  134. package/skills/pr-converge/scripts/test_check_convergence_gates.py +68 -0
  135. package/skills/pr-converge/scripts/test_check_convergence_thread_gates.py +75 -0
  136. package/skills/pr-fix-protocol/SKILL.md +20 -20
  137. package/skills/privacy-hygiene/SKILL.md +4 -3
  138. package/skills/reviewer-gates/SKILL.md +26 -8
  139. package/skills/session-log/SKILL.md +11 -12
  140. package/skills/session-tidy/SKILL.md +40 -30
  141. package/skills/skill-builder/CLAUDE.md +13 -10
  142. package/skills/skill-builder/SKILL.md +31 -31
  143. package/skills/skill-builder/references/CLAUDE.md +10 -6
  144. package/skills/skill-builder/references/delegation-map.md +13 -4
  145. package/skills/skill-builder/references/description-field.md +113 -0
  146. package/skills/skill-builder/references/self-audit-checklist.md +21 -4
  147. package/skills/skill-builder/references/skill-modularity.md +113 -0
  148. package/skills/skill-builder/references/skill-types.md +4 -0
  149. package/skills/skill-builder/templates/CLAUDE.md +4 -4
  150. package/skills/skill-builder/templates/gap-analysis.md +25 -1
  151. package/skills/skill-builder/workflows/CLAUDE.md +6 -4
  152. package/skills/skill-builder/workflows/improve-skill.md +17 -16
  153. package/skills/skill-builder/workflows/new-skill.md +34 -10
  154. package/skills/skill-builder/workflows/polish-skill.md +59 -43
  155. package/skills/team-advisor/SKILL.md +15 -11
  156. package/skills/usage-pause/SKILL.md +10 -14
  157. package/system-prompts/software-engineer.xml +7 -6
  158. package/hooks/validators/test_verify_paths.py +0 -32
  159. package/hooks/validators/verify_paths.py +0 -57
  160. package/skills/bdd-protocol/CLAUDE.md +0 -26
  161. package/skills/bdd-protocol/SKILL.md +0 -30
  162. package/skills/bdd-protocol/references/CLAUDE.md +0 -10
  163. package/skills/bdd-protocol/references/anti-patterns.md +0 -26
  164. package/skills/bdd-protocol/references/example-mapping.md +0 -23
  165. package/skills/bg-agent/CLAUDE.md +0 -17
  166. package/skills/bg-agent/SKILL.md +0 -69
  167. package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_code_rules_gate_constants.py +0 -55
  168. package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_fix_hookspath_constants.py +0 -26
  169. package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_preflight_constants.py +0 -35
  170. package/skills/caveman/CLAUDE.md +0 -15
  171. package/skills/caveman/SKILL.md +0 -38
  172. package/skills/code/CLAUDE.md +0 -17
  173. package/skills/code/SKILL.md +0 -178
  174. package/skills/deep-research/CLAUDE.md +0 -17
  175. package/skills/deep-research/SKILL.md +0 -80
  176. package/skills/findbugs/CLAUDE.md +0 -20
  177. package/skills/findbugs/SKILL.md +0 -241
  178. package/skills/fixbugs/CLAUDE.md +0 -19
  179. package/skills/fixbugs/SKILL.md +0 -142
  180. package/skills/gh-paginate/CLAUDE.md +0 -18
  181. package/skills/gh-paginate/SKILL.md +0 -84
  182. package/skills/gotcha/CLAUDE.md +0 -33
  183. package/skills/gotcha/SKILL.md +0 -73
  184. package/skills/implement/CLAUDE.md +0 -27
  185. package/skills/implement/SKILL.md +0 -66
  186. package/skills/implement/scripts/CLAUDE.md +0 -22
  187. package/skills/implement/scripts/append_note.py +0 -133
  188. package/skills/implement/scripts/implement_scripts_constants/CLAUDE.md +0 -22
  189. package/skills/implement/scripts/implement_scripts_constants/__init__.py +0 -0
  190. package/skills/implement/scripts/implement_scripts_constants/notes_constants.py +0 -12
  191. package/skills/implement/scripts/test_append_note.py +0 -191
  192. package/skills/log-audit/CLAUDE.md +0 -20
  193. package/skills/log-audit/SKILL.md +0 -66
  194. package/skills/log-audit/reference/CLAUDE.md +0 -9
  195. package/skills/log-audit/reference/charter.md +0 -52
  196. package/skills/log-audit/scripts/CLAUDE.md +0 -27
  197. package/skills/log-audit/scripts/cluster_recurrences.py +0 -261
  198. package/skills/log-audit/scripts/collect_log_window.py +0 -199
  199. package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +0 -12
  200. package/skills/log-audit/scripts/log_audit_constants/__init__.py +0 -0
  201. package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +0 -23
  202. package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +0 -24
  203. package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +0 -49
  204. package/skills/log-audit/scripts/mine_copilot_findings.py +0 -302
  205. package/skills/log-audit/scripts/test_cluster_recurrences.py +0 -160
  206. package/skills/log-audit/scripts/test_collect_log_window.py +0 -111
  207. package/skills/log-audit/scripts/test_mine_copilot_findings.py +0 -126
  208. package/skills/logifix/CLAUDE.md +0 -36
  209. package/skills/logifix/SKILL.md +0 -69
  210. package/skills/logifix/scripts/CLAUDE.md +0 -16
  211. package/skills/logifix/scripts/logifix.ps1 +0 -205
  212. package/skills/monitor-open-prs/CLAUDE.md +0 -34
  213. package/skills/monitor-open-prs/SKILL.md +0 -88
  214. package/skills/monitor-open-prs/scripts/CLAUDE.md +0 -17
  215. package/skills/monitor-open-prs/scripts/discover_open_prs.py +0 -69
  216. package/skills/monitor-open-prs/scripts/test_discover_open_prs.py +0 -149
  217. package/skills/monitor-open-prs/test_skill_contract.py +0 -27
  218. package/skills/post-audit-findings/SKILL.md +0 -80
  219. package/skills/pr-consistency-audit/CLAUDE.md +0 -34
  220. package/skills/pr-consistency-audit/SKILL.md +0 -116
  221. package/skills/pr-consistency-audit/reference/CLAUDE.md +0 -16
  222. package/skills/pr-consistency-audit/reference/detection-rules.md +0 -96
  223. package/skills/pr-consistency-audit/reference/illustrations.md +0 -78
  224. package/skills/pr-review-responder/CLAUDE.md +0 -35
  225. package/skills/pr-review-responder/EXAMPLES.md +0 -590
  226. package/skills/pr-review-responder/PRINCIPLES.md +0 -533
  227. package/skills/pr-review-responder/README.md +0 -168
  228. package/skills/pr-review-responder/SKILL.md +0 -203
  229. package/skills/pr-review-responder/TESTING.md +0 -350
  230. package/skills/pr-scope-resolve/SKILL.md +0 -45
  231. package/skills/pre-compact/CLAUDE.md +0 -24
  232. package/skills/pre-compact/SKILL.md +0 -134
  233. package/skills/qbug/CLAUDE.md +0 -40
  234. package/skills/qbug/SKILL.md +0 -387
  235. package/skills/qbug/test_qbug_skill_audit_schema.py +0 -152
  236. package/skills/qbug/test_qbug_skill_post_fix_audit.py +0 -103
  237. package/skills/refine/CLAUDE.md +0 -44
  238. package/skills/refine/SKILL.md +0 -262
  239. package/skills/refine/templates/CLAUDE.md +0 -17
  240. package/skills/refine/templates/implementation-notes-template.html +0 -56
  241. package/skills/refine/templates/plan-template.md +0 -60
  242. package/skills/research-mode/CLAUDE.md +0 -35
  243. package/skills/research-mode/SKILL.md +0 -53
  244. package/skills/structure-prompt/CLAUDE.md +0 -42
  245. package/skills/structure-prompt/SKILL.md +0 -44
  246. package/skills/structure-prompt/reference/CLAUDE.md +0 -28
  247. package/skills/structure-prompt/reference/adversarial-tuning.md +0 -62
  248. package/skills/structure-prompt/reference/block-classification.md +0 -27
  249. package/skills/structure-prompt/reference/canonical-case.md +0 -48
  250. package/skills/structure-prompt/reference/citation-depth.md +0 -70
  251. package/skills/structure-prompt/reference/cleanup.md +0 -33
  252. package/skills/structure-prompt/reference/constraints.md +0 -33
  253. package/skills/structure-prompt/reference/directives.md +0 -37
  254. package/skills/structure-prompt/reference/examples.md +0 -72
  255. package/skills/structure-prompt/reference/instantiation.md +0 -51
  256. package/skills/structure-prompt/reference/output-contract.md +0 -72
  257. package/skills/structure-prompt/reference/per-category.md +0 -23
  258. package/skills/structure-prompt/reference/persona.md +0 -38
  259. package/skills/structure-prompt/reference/research.md +0 -33
  260. package/skills/structure-prompt/reference/structure.md +0 -28
  261. package/skills/verified-build/CLAUDE.md +0 -33
  262. package/skills/verified-build/SKILL.md +0 -33
@@ -0,0 +1,350 @@
1
+ Set-StrictMode -Version Latest
2
+
3
+ BeforeAll {
4
+ $scriptUnderTest = Join-Path (Split-Path -Parent $PSScriptRoot) 'Get-SessionAccount.ps1'
5
+ . $scriptUnderTest
6
+
7
+ function New-Utf16StorageFile {
8
+ param(
9
+ [string]$ProfileDirectory,
10
+ [string]$StoreName,
11
+ [string]$FileName,
12
+ [string]$EmailText
13
+ )
14
+ $storeDirectory = Join-Path $ProfileDirectory $StoreName
15
+ New-Item -ItemType Directory -Path $storeDirectory -Force | Out-Null
16
+ $emailBytes = [System.Text.Encoding]::Unicode.GetBytes("`0`0$EmailText`0`0")
17
+ $filePath = Join-Path $storeDirectory $FileName
18
+ [System.IO.File]::WriteAllBytes($filePath, $emailBytes)
19
+ }
20
+
21
+ function New-Utf8StorageFile {
22
+ param(
23
+ [string]$ProfileDirectory,
24
+ [string]$StoreName,
25
+ [string]$FileName,
26
+ [string]$JsonText
27
+ )
28
+ $storeDirectory = Join-Path $ProfileDirectory $StoreName
29
+ New-Item -ItemType Directory -Path $storeDirectory -Force | Out-Null
30
+ $filePath = Join-Path $storeDirectory $FileName
31
+ [System.IO.File]::WriteAllText($filePath, $JsonText, [System.Text.Encoding]::UTF8)
32
+ }
33
+
34
+ function New-CliConfigFile {
35
+ param(
36
+ [string]$Directory,
37
+ [string]$Email,
38
+ [string]$AccountUuid
39
+ )
40
+ New-Item -ItemType Directory -Path $Directory -Force | Out-Null
41
+ $cliConfigPath = Join-Path $Directory '.claude.json'
42
+ $cliConfigJson = [pscustomobject]@{
43
+ oauthAccount = [pscustomobject]@{
44
+ emailAddress = $Email
45
+ accountUuid = $AccountUuid
46
+ }
47
+ } | ConvertTo-Json
48
+ [System.IO.File]::WriteAllText($cliConfigPath, $cliConfigJson, [System.Text.Encoding]::UTF8)
49
+ return $cliConfigPath
50
+ }
51
+
52
+ function New-ProfileConfigFile {
53
+ param(
54
+ [string]$ProfileDirectory,
55
+ [string]$LastKnownAccountUuid
56
+ )
57
+ New-Item -ItemType Directory -Path $ProfileDirectory -Force | Out-Null
58
+ $profileConfigPath = Join-Path $ProfileDirectory 'config.json'
59
+ $profileConfigJson = [pscustomobject]@{
60
+ lastKnownAccountUuid = $LastKnownAccountUuid
61
+ } | ConvertTo-Json
62
+ [System.IO.File]::WriteAllText($profileConfigPath, $profileConfigJson, [System.Text.Encoding]::UTF8)
63
+ }
64
+ }
65
+
66
+ Describe 'Test-NoiseEmail' {
67
+ It 'rejects the placeholder example domain' {
68
+ (Test-NoiseEmail -Email 'noreply@example.com') | Should -Be $true
69
+ }
70
+
71
+ It 'keeps a legitimate local part that contains the substring example' {
72
+ (Test-NoiseEmail -Email 'sam.exampleson@company.com') | Should -Be $false
73
+ }
74
+
75
+ It 'keeps a legitimate domain that merely contains the substring example' {
76
+ (Test-NoiseEmail -Email 'person@example-labs.io') | Should -Be $false
77
+ }
78
+
79
+ It 'still rejects sentry and anthropic noise addresses' {
80
+ (Test-NoiseEmail -Email 'someone@sentry.io') | Should -Be $true
81
+ (Test-NoiseEmail -Email 'billing@anthropic.com') | Should -Be $true
82
+ }
83
+
84
+ It 'rejects a sentry ingest subdomain address' {
85
+ (Test-NoiseEmail -Email 'abc@o123.ingest.sentry.io') | Should -Be $true
86
+ }
87
+
88
+ It 'keeps an address whose local part merely contains sentry.io' {
89
+ (Test-NoiseEmail -Email 'sentry.io.reports@realcompany.com') | Should -Be $false
90
+ }
91
+
92
+ It 'keeps an address whose domain merely starts with anthropic' {
93
+ (Test-NoiseEmail -Email 'user@anthropic-partner.com') | Should -Be $false
94
+ }
95
+ }
96
+
97
+ Describe 'Get-EmailCandidatesFromProfile' {
98
+ It 'recovers an email persisted as UTF-16 in Session Storage' {
99
+ $profileDirectory = Join-Path $TestDrive 'utf16-profile'
100
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000003.ldb' -EmailText 'user@host.com'
101
+
102
+ $candidateEmails = @(Get-EmailCandidatesFromProfile -ProfileDirectory $profileDirectory)
103
+
104
+ ($candidateEmails -contains 'user@host.com') | Should -Be $true
105
+ }
106
+
107
+ It 'recovers an email stored as UTF-8 JSON in the sentry store' {
108
+ $profileDirectory = Join-Path $TestDrive 'utf8-profile'
109
+ New-Utf8StorageFile -ProfileDirectory $profileDirectory -StoreName 'sentry' -FileName 'events.json' -JsonText '{"user":{"email":"person@company.com"}}'
110
+
111
+ $candidateEmails = @(Get-EmailCandidatesFromProfile -ProfileDirectory $profileDirectory)
112
+
113
+ ($candidateEmails -contains 'person@company.com') | Should -Be $true
114
+ }
115
+
116
+ It 'keeps a single UTF-16 email whose local part contains the substring example' {
117
+ $profileDirectory = Join-Path $TestDrive 'example-profile'
118
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000004.ldb' -EmailText 'sam.exampleson@company.com'
119
+
120
+ $candidateEmails = @(Get-EmailCandidatesFromProfile -ProfileDirectory $profileDirectory)
121
+
122
+ $candidateEmails.Count | Should -Be 1
123
+ $candidateEmails[0] | Should -Be 'sam.exampleson@company.com'
124
+ }
125
+
126
+ It 'counts the same email recovered with differing casing across stores as one candidate' {
127
+ $profileDirectory = Join-Path $TestDrive 'mixed-case-profile'
128
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000012.ldb' -EmailText 'Desktop@Company.com'
129
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'IndexedDB' -FileName '000013.ldb' -EmailText 'desktop@company.com'
130
+
131
+ $candidateEmails = @(Get-EmailCandidatesFromProfile -ProfileDirectory $profileDirectory)
132
+
133
+ $candidateEmails.Count | Should -Be 1
134
+ }
135
+
136
+ It 'refuses to recover an email whose local part is glued to an adjacent boundary byte' {
137
+ $profileDirectory = Join-Path $TestDrive 'prefix-polluted-profile'
138
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000010.ldb' -EmailText '.desktop@company.com'
139
+
140
+ $candidateEmails = @(Get-EmailCandidatesFromProfile -ProfileDirectory $profileDirectory)
141
+
142
+ ($candidateEmails -contains '.desktop@company.com') | Should -Be $false
143
+ $candidateEmails.Count | Should -Be 0
144
+ }
145
+ }
146
+
147
+ Describe 'Resolve-SessionAccount' {
148
+ It 'returns exit code 2 when the CLI config file is absent' {
149
+ $cliConfigPath = Join-Path $TestDrive 'absent-cli/.claude.json'
150
+
151
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory ''
152
+
153
+ $sessionAccount.ExitCode | Should -Be 2
154
+ $sessionAccount.ErrorMessage | Should -Match 'CLI config not found'
155
+ }
156
+
157
+ It 'returns exit code 2 when the CLI config is not valid JSON' {
158
+ $configDirectory = Join-Path $TestDrive 'unparseable-cli'
159
+ New-Item -ItemType Directory -Path $configDirectory -Force | Out-Null
160
+ $cliConfigPath = Join-Path $configDirectory '.claude.json'
161
+ [System.IO.File]::WriteAllText($cliConfigPath, 'this is not json {', [System.Text.Encoding]::UTF8)
162
+
163
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory ''
164
+
165
+ $sessionAccount.ExitCode | Should -Be 2
166
+ $sessionAccount.ErrorMessage | Should -Match 'Failed to parse CLI config'
167
+ }
168
+
169
+ It 'returns exit code 2 when the CLI config top level is a JSON string' {
170
+ $configDirectory = Join-Path $TestDrive 'scalar-cli'
171
+ New-Item -ItemType Directory -Path $configDirectory -Force | Out-Null
172
+ $cliConfigPath = Join-Path $configDirectory '.claude.json'
173
+ [System.IO.File]::WriteAllText($cliConfigPath, '"just a string"', [System.Text.Encoding]::UTF8)
174
+
175
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory ''
176
+
177
+ $sessionAccount.ExitCode | Should -Be 2
178
+ $sessionAccount.ErrorMessage | Should -Match 'not a JSON object'
179
+ }
180
+
181
+ It 'returns exit code 2 when the CLI config top level is a JSON array' {
182
+ $configDirectory = Join-Path $TestDrive 'array-cli'
183
+ New-Item -ItemType Directory -Path $configDirectory -Force | Out-Null
184
+ $cliConfigPath = Join-Path $configDirectory '.claude.json'
185
+ [System.IO.File]::WriteAllText($cliConfigPath, '[1, 2, 3]', [System.Text.Encoding]::UTF8)
186
+
187
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory ''
188
+
189
+ $sessionAccount.ExitCode | Should -Be 2
190
+ $sessionAccount.ErrorMessage | Should -Match 'not a JSON object'
191
+ }
192
+
193
+ It 'returns exit code 2 when the desktop profile config top level is not a JSON object' {
194
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'scalar-profile-cli') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
195
+ $profileDirectory = Join-Path $TestDrive 'scalar-profile'
196
+ New-Item -ItemType Directory -Path $profileDirectory -Force | Out-Null
197
+ $profileConfigPath = Join-Path $profileDirectory 'config.json'
198
+ [System.IO.File]::WriteAllText($profileConfigPath, '42', [System.Text.Encoding]::UTF8)
199
+
200
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
201
+
202
+ $sessionAccount.ExitCode | Should -Be 2
203
+ $sessionAccount.ErrorMessage | Should -Match 'not a JSON object'
204
+ }
205
+
206
+ It 'returns exit code 2 when the CLI config lacks oauthAccount fields' {
207
+ $configDirectory = Join-Path $TestDrive 'incomplete-cli'
208
+ New-Item -ItemType Directory -Path $configDirectory -Force | Out-Null
209
+ $cliConfigPath = Join-Path $configDirectory '.claude.json'
210
+ [System.IO.File]::WriteAllText($cliConfigPath, '{"oauthAccount":{"emailAddress":"","accountUuid":""}}', [System.Text.Encoding]::UTF8)
211
+
212
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory ''
213
+
214
+ $sessionAccount.ExitCode | Should -Be 2
215
+ $sessionAccount.ErrorMessage | Should -Match 'missing oauthAccount'
216
+ }
217
+
218
+ It 'reports the cli-config account with exit code 0 when no desktop profile is set' {
219
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'cli-only') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
220
+
221
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory ''
222
+
223
+ $sessionAccount.ExitCode | Should -Be 0
224
+ $sessionAccount.Source | Should -Be 'cli-config'
225
+ $sessionAccount.Email | Should -Be 'cli@company.com'
226
+ }
227
+
228
+ It 'returns exit code 2 when the desktop profile config is absent' {
229
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'missing-profile-cli') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
230
+ $profileDirectory = Join-Path $TestDrive 'profile-without-config'
231
+ New-Item -ItemType Directory -Path $profileDirectory -Force | Out-Null
232
+
233
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
234
+
235
+ $sessionAccount.ExitCode | Should -Be 2
236
+ $sessionAccount.ErrorMessage | Should -Match 'Desktop profile config not found'
237
+ }
238
+
239
+ It 'reports the matching desktop-profile account with exit code 0' {
240
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'match-cli') -Email 'cli@company.com' -AccountUuid 'uuid-shared'
241
+ $profileDirectory = Join-Path $TestDrive 'match-profile'
242
+ New-ProfileConfigFile -ProfileDirectory $profileDirectory -LastKnownAccountUuid 'uuid-shared'
243
+
244
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
245
+
246
+ $sessionAccount.ExitCode | Should -Be 0
247
+ $sessionAccount.Source | Should -Be 'desktop-profile (matches cli-config)'
248
+ $sessionAccount.Email | Should -Be 'cli@company.com'
249
+ }
250
+
251
+ It 'recovers the desktop account email with exit code 0 when exactly one candidate differs from the cli account' {
252
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'differ-cli') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
253
+ $profileDirectory = Join-Path $TestDrive 'differ-profile'
254
+ New-ProfileConfigFile -ProfileDirectory $profileDirectory -LastKnownAccountUuid 'uuid-desktop'
255
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000005.ldb' -EmailText 'desktop@company.com'
256
+
257
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
258
+
259
+ $sessionAccount.ExitCode | Should -Be 0
260
+ $sessionAccount.Email | Should -Be 'desktop@company.com'
261
+ $sessionAccount.AccountUuid | Should -Be 'uuid-desktop'
262
+ $sessionAccount.Source | Should -Be 'desktop-profile (differs from cli-config)'
263
+ $sessionAccount.CliEmail | Should -Be 'cli@company.com'
264
+ }
265
+
266
+ It 'recovers the desktop email even when the known cli email also lingers in profile storage' {
267
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'lingering-cli') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
268
+ $profileDirectory = Join-Path $TestDrive 'lingering-profile'
269
+ New-ProfileConfigFile -ProfileDirectory $profileDirectory -LastKnownAccountUuid 'uuid-desktop'
270
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000008.ldb' -EmailText 'desktop@company.com'
271
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'IndexedDB' -FileName '000009.ldb' -EmailText 'cli@company.com'
272
+
273
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
274
+
275
+ $sessionAccount.ExitCode | Should -Be 0
276
+ $sessionAccount.Email | Should -Be 'desktop@company.com'
277
+ $sessionAccount.AccountUuid | Should -Be 'uuid-desktop'
278
+ $sessionAccount.CliEmail | Should -Be 'cli@company.com'
279
+ }
280
+
281
+ It 'fails safe with exit code 1 rather than reporting a prefix-polluted email as the account' {
282
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'polluted-cli') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
283
+ $profileDirectory = Join-Path $TestDrive 'polluted-resolve-profile'
284
+ New-ProfileConfigFile -ProfileDirectory $profileDirectory -LastKnownAccountUuid 'uuid-desktop'
285
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000011.ldb' -EmailText '.desktop@company.com'
286
+
287
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
288
+
289
+ $sessionAccount.ExitCode | Should -Be 1
290
+ $sessionAccount.Email | Should -BeNullOrEmpty
291
+ $sessionAccount.ErrorMessage | Should -Match 'no candidate email was recovered'
292
+ }
293
+
294
+ It 'returns exit code 1 when the desktop account differs but no candidate email is recovered' {
295
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'none-cli') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
296
+ $profileDirectory = Join-Path $TestDrive 'none-profile'
297
+ New-ProfileConfigFile -ProfileDirectory $profileDirectory -LastKnownAccountUuid 'uuid-desktop'
298
+
299
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
300
+
301
+ $sessionAccount.ExitCode | Should -Be 1
302
+ $sessionAccount.ErrorMessage | Should -Match 'no candidate email was recovered'
303
+ }
304
+
305
+ It 'returns exit code 1 when the desktop account differs and multiple candidate emails are found' {
306
+ $cliConfigPath = New-CliConfigFile -Directory (Join-Path $TestDrive 'multi-cli') -Email 'cli@company.com' -AccountUuid 'uuid-cli'
307
+ $profileDirectory = Join-Path $TestDrive 'multi-profile'
308
+ New-ProfileConfigFile -ProfileDirectory $profileDirectory -LastKnownAccountUuid 'uuid-desktop'
309
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'Session Storage' -FileName '000006.ldb' -EmailText 'first@company.com'
310
+ New-Utf16StorageFile -ProfileDirectory $profileDirectory -StoreName 'IndexedDB' -FileName '000007.ldb' -EmailText 'second@company.com'
311
+
312
+ $sessionAccount = Resolve-SessionAccount -CliConfigPath $cliConfigPath -ProfileDirectory $profileDirectory
313
+
314
+ $sessionAccount.ExitCode | Should -Be 1
315
+ $sessionAccount.ErrorMessage | Should -Match 'multiple candidate emails'
316
+ }
317
+ }
318
+
319
+ Describe 'Write-AccountResult' {
320
+ It 'writes the account fields as text without cli lines when no CliEmail is given' {
321
+ $textLines = Write-AccountResult -Email 'a@company.com' -AccountUuid 'uuid-a' -Source 'cli-config'
322
+ $joinedText = $textLines -join "`n"
323
+
324
+ $joinedText | Should -Match 'Account: a@company.com'
325
+ $joinedText | Should -Match 'AccountUuid: uuid-a'
326
+ $joinedText | Should -Match 'Source: cli-config'
327
+ $joinedText | Should -Not -Match 'CliAccount:'
328
+ }
329
+
330
+ It 'writes the cli account lines as text when a CliEmail is given' {
331
+ $textLines = Write-AccountResult -Email 'd@company.com' -AccountUuid 'uuid-d' -Source 'desktop-profile (differs from cli-config)' -CliEmail 'c@company.com' -CliAccountUuid 'uuid-c'
332
+ $joinedText = $textLines -join "`n"
333
+
334
+ $joinedText | Should -Match 'Account: d@company.com'
335
+ $joinedText | Should -Match 'CliAccount: c@company.com'
336
+ $joinedText | Should -Match 'CliAccountUuid: uuid-c'
337
+ }
338
+
339
+ It 'emits a JSON object carrying the account contract fields when AsJson is set' {
340
+ $AsJson = $true
341
+ $jsonOutput = Write-AccountResult -Email 'd@company.com' -AccountUuid 'uuid-d' -Source 'desktop-profile (differs from cli-config)' -CliEmail 'c@company.com' -CliAccountUuid 'uuid-c' -AsJson:$AsJson
342
+ $parsedResult = $jsonOutput | ConvertFrom-Json
343
+
344
+ $parsedResult.account | Should -Be 'd@company.com'
345
+ $parsedResult.accountUuid | Should -Be 'uuid-d'
346
+ $parsedResult.source | Should -Be 'desktop-profile (differs from cli-config)'
347
+ $parsedResult.cliAccount | Should -Be 'c@company.com'
348
+ $parsedResult.cliAccountUuid | Should -Be 'uuid-c'
349
+ }
350
+ }
package/skills/CLAUDE.md CHANGED
@@ -17,61 +17,40 @@ 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 across the PR-loop skills, and `advisor/`, which provides the shared warm-advisor protocol used by `team-advisor` and `orchestrator`.
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`, `orchestrator`, and `orchestrator-refresh`.
21
21
 
22
22
  ## Skill groups
23
23
 
24
24
  **Planning and implementation**
25
25
  - `anthropic-plan` — creates a source-grounded plan packet before any code changes
26
- - `implement` — structured implementation from an existing plan packet
27
- - `bdd-protocol` — BDD depth: Example Mapping, scenario quality, outside-in layout
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; 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
26
+ - `orchestrator` — turns the session into the 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: max-tier Claude via CLI Claude-chain)
27
+ - `orchestrator-refresh` — sub-skill fired by the `/orchestrator` loop to re-assert the host-matched shared-advisor discipline mid-run (Claude SendMessage; Grok Claude CLI chain, no Agent-tool advisor spawn)
28
+ - `team-advisor` — binds one advisor at the strongest reachable tier (Claude warm agent; Grok max-tier Claude via CLI Claude-chain, fail closed when unreachable) and consults it for a second opinion before a big decision, at completion, when stuck, or when reconsidering the approach
32
29
 
33
30
  **PR review and convergence**
34
31
  - `autoconverge` — autonomous single-run workflow that drives a PR to ready
35
32
  - `pr-converge` — paced convergence loop across `ScheduleWakeup` ticks
36
33
  - `bugteam` — open-loop audit-fix until convergence
37
- - `pr-review-responder` — fetches all reviewer comments and replies systematically
38
- - `pr-consistency-audit` — cross-file consistency check on a PR diff
39
34
  - `copilot-review` — requests and polls a GitHub Copilot review
40
- - `findbugs` / `fixbugs` find bugs then fix them in separate passes
35
+ - `copilot-finding-triage` tiers each Copilot gate finding, verifies each code concern with an executed check, then routes it (auto-fix a confirmed defect, resolve a refuted one, page the user only for an inconclusive one)
41
36
  - `reviewer-gates` — availability gates for external reviewers (opt-out parse, Copilot quota, Bugbot trigger/detect)
42
- - `pr-scope-resolve` — one resolution ladder for a PR-loop skill's audit/fix target
43
- - `pr-fix-protocol` — fix, reply, and resolve reviewer findings; the unresolved-thread sweep
44
- - `post-audit-findings` — publishes an audit pass as one GitHub PR review
37
+ - `pr-fix-protocol` — applies reviewer findings as verified fixes and drives unresolved review threads to zero
45
38
  - `pr-loop-lifecycle` — opens and closes a PR-loop run (grant, teardown, PR description, revoke, report)
46
39
  - `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)
47
- - `code` — strict-mode code generation session
48
40
 
49
41
  **Research and discovery**
50
- - `deep-research` — multi-source research with citation
51
- - `research-mode` — activates anti-hallucination discipline for a session
52
42
  - `recall` — retrieves facts from memory files
53
43
  - `remember` — saves a decision, gotcha, or architectural choice to the Obsidian vault
54
44
  - `everything-search` — file-system search via the Everything `es.exe` CLI
55
- - `caveman` — trims noise from a draft artifact
56
45
 
57
46
  **Session and workflow management**
58
47
  - `session-log` — logs a session report to the Obsidian vault
59
48
  - `session-tidy` — tidies the session folder
60
- - `bg-agent` — launches a background agent
61
49
  - `task-build` — gathers open tasks
62
50
  - `privacy-hygiene` — full-repo personal-data and secret sweep plus remediation guide
63
51
  - `update` — updates the dev-env package
64
- - `gh-paginate` — safe `gh api` pagination patterns
65
52
  - `fresh-branch` — creates a clean branch off main
66
53
  - `rebase` — rebases onto main
67
- - `gotcha` — records a hard-won lesson to memory
68
- - `logifix` — restores the Logitech Gaming Software (LCore) tray icon when it disappears on Windows
69
- - `refine` — refinement pass on an artifact
70
- - `structure-prompt` — structures a freeform prompt
71
- - `monitor-open-prs` — polls open PRs for status
72
- - `pre-compact` — compact-safe session handoff
73
- - `qbug` — required baseline PR audit; one clean-coder subagent loops audit → fix → commit → push until clean or stuck
74
54
  - `usage-pause` — waits out the 5-hour usage window in ScheduleWakeup stages that keep agent contexts warm; probes the OAuth usage endpoint or takes a manual reset override
75
55
  - `skill-builder` — complete skill-building lifecycle
76
56
  - `auditing-claude-config` — audits a Claude Code setup for context-budget waste and produces a migration table with savings
77
- - `log-audit` — background agent that audits this repo's own logs for recurring errors and timing regressions and files grouped fixes
@@ -48,19 +48,7 @@ The workflow writes the packet into the live checkout under `docs/plans/<slug>/`
48
48
 
49
49
  ## Workflow Contract
50
50
 
51
- The workflow handles the full planning loop:
52
-
53
- 1. Resolve repo root and packet path.
54
- 2. Read project instructions, rules, relevant skills, manifests, docs, tests, hooks, agents, commands, configs, and workflows.
55
- 3. Build a source inventory and extract source facts into `context/source-map.md`.
56
- 4. Write the packet under `docs/plans/<slug>/`.
57
- 5. Run `packages/claude-dev-env/skills/anthropic-plan/scripts/validate_packet.py`.
58
- 6. Spawn `plan-packet-validator` in fresh context.
59
- 7. Repair packet findings up to the workflow cap.
60
- 8. Run the reuse audit: search the codebase for existing equivalents of each new file/symbol the packet introduces, write `validation/reuse-audit.md`, and gate approval on any unjustified reproduction.
61
- 9. Build a single-file offline visual HTML of the finished packet from `templates/visual-plan.template.html` and write it beside the packet as `visual-plan.html`.
62
- 10. Return packet path, validation state, and findings.
63
- 11. Stop before implementation.
51
+ Phases run inside `workflow/plan-packet.mjs` (Discover → Write packet under `docs/plans/<slug>/` → Validate with `validate_packet.py` and `plan-packet-validator` → Reuse audit → Visualize → Approval). The workflow returns the packet path and validation state, then **stop before implementation**. Phase detail lives in that script's `phases` list.
64
52
 
65
53
  ## Packet Shape
66
54
 
@@ -21,9 +21,12 @@ Drives one draft PR to convergence in a single autonomous workflow run. Each rou
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
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
- | `reference/stop-conditions.md` | Every way the run ends short of ready. |
24
+ | `reference/stop-conditions.md` | Every way the run ends short of ready, including the budget stop. |
25
25
  | `reference/gotchas.md` | Hard-won failure lessons. |
26
- | `reference/closing-report.md` | Specification for the closing HTML report format. |
26
+ | `reference/closing-report.md` | The closing HTML report: data source, build steps, publishing. |
27
+ | `reference/multi-pr.md` | The several-PRs path: per-PR worktrees, the `converge_multi.mjs` launch, per-PR teardown. |
28
+ | `reference/self-closing-loop.md` | The deferred-PR generations and the Conventional-Commit title rule. |
29
+ | `reference/headless-safety.md` | The agent-prompt headless-safety preamble and the rm auto-allow paths. |
27
30
 
28
31
  ## Entry point
29
32