claude-dev-env 1.79.0 → 1.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_shared/pr-loop/scripts/CLAUDE.md +3 -1
- package/_shared/pr-loop/scripts/code_rules_gate.py +116 -30
- package/_shared/pr-loop/scripts/copilot_quota.py +360 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +2 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +13 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/copilot_quota_constants.py +24 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +113 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +467 -0
- package/_shared/pr-loop/scripts/tests/CLAUDE.md +8 -0
- package/_shared/pr-loop/scripts/tests/fixtures/copilot_internal_user_jonecho.json +76 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +339 -0
- package/_shared/pr-loop/scripts/tests/test_copilot_quota.py +242 -0
- package/_shared/pr-loop/scripts/tests/test_copilot_quota_constants.py +63 -0
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +297 -0
- package/audit-rubrics/CLAUDE.md +3 -2
- package/audit-rubrics/category_rubrics/CLAUDE.md +2 -1
- package/audit-rubrics/category_rubrics/category-a-api-contracts.md +2 -1
- package/audit-rubrics/category_rubrics/category-j-code-rules-compliance.md +13 -1
- package/audit-rubrics/category_rubrics/category-p-name-vs-behavior-contract.md +19 -0
- package/audit-rubrics/category_rubrics/category-q-cross-surface-claims.md +46 -0
- package/audit-rubrics/prompts/CLAUDE.md +2 -1
- package/audit-rubrics/prompts/category-a-api-contracts.md +1 -0
- package/audit-rubrics/prompts/category-j-code-rules-compliance.md +19 -7
- package/audit-rubrics/prompts/category-p-name-vs-behavior-contract.md +14 -0
- package/audit-rubrics/prompts/category-q-cross-surface-claims.md +51 -0
- package/docs/CODE_RULES.md +2 -2
- package/hooks/blocking/CLAUDE.md +2 -0
- package/hooks/blocking/code_rules_annotations_length.py +59 -11
- package/hooks/blocking/code_rules_banned_identifiers.py +48 -9
- package/hooks/blocking/code_rules_command_dispatch.py +140 -0
- package/hooks/blocking/code_rules_docstrings.py +93 -0
- package/hooks/blocking/code_rules_enforcer.py +58 -4
- package/hooks/blocking/code_rules_imports_logging.py +136 -1
- package/hooks/blocking/code_rules_js_conventions.py +246 -0
- package/hooks/blocking/code_rules_naming_collection.py +5 -0
- package/hooks/blocking/code_rules_test_assertions.py +3 -0
- package/hooks/blocking/code_rules_unused_imports.py +7 -66
- package/hooks/blocking/duplicate_rmtree_helper_blocker.py +7 -0
- package/hooks/blocking/test_code_rules_command_dispatch.py +95 -0
- package/hooks/blocking/test_code_rules_enforcer_annotations.py +20 -2
- package/hooks/blocking/test_code_rules_enforcer_banned_identifier.py +10 -2
- package/hooks/blocking/test_code_rules_enforcer_banned_import_alias.py +8 -4
- package/hooks/blocking/test_code_rules_enforcer_dispatch_wiring.py +9 -3
- package/hooks/blocking/test_code_rules_enforcer_docstring_type_checking_gate.py +164 -0
- package/hooks/blocking/test_code_rules_enforcer_js_returns_object.py +72 -0
- package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +112 -18
- package/hooks/blocking/test_code_rules_js_conventions.py +167 -0
- package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +167 -0
- package/hooks/hooks_constants/CLAUDE.md +2 -0
- package/hooks/hooks_constants/blocking_check_limits.py +10 -0
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +14 -0
- package/hooks/hooks_constants/command_dispatch_constants.py +28 -0
- package/hooks/hooks_constants/js_conventions_constants.py +54 -0
- package/hooks/hooks_constants/test_code_rules_enforcer_constants.py +93 -0
- package/hooks/hooks_constants/unused_module_import_constants.py +0 -1
- package/package.json +1 -1
- package/rules/docstring-prose-matches-implementation.md +3 -1
- package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +43 -1
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +2 -2
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +1 -4
- package/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +100 -4
- package/skills/autoconverge/SKILL.md +28 -7
- package/skills/autoconverge/reference/convergence.md +3 -3
- package/skills/autoconverge/reference/stop-conditions.md +1 -1
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +4 -4
- package/skills/autoconverge/workflow/converge.contract.test.mjs +58 -122
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +289 -5
- package/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +50 -46
- package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +6 -6
- package/skills/autoconverge/workflow/converge.mjs +235 -247
- package/skills/autoconverge/workflow/converge.run-input.test.mjs +11 -0
- package/skills/autoconverge/workflow/converge_multi.mjs +23 -7
- package/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +28 -2
- package/skills/pr-converge/SKILL.md +28 -2
- package/skills/pr-converge/reference/convergence-gates.md +13 -1
- package/skills/pr-converge/reference/state-schema.md +11 -0
|
@@ -99,8 +99,8 @@ test('FIX_RECOVERY_MAX_ATTEMPTS is declared and bounds the recovery loop at 2',
|
|
|
99
99
|
assert.match(constantLine('FIX_RECOVERY_MAX_ATTEMPTS'), /=\s*2\s*$/);
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
test('the commit path in
|
|
103
|
-
const commitBody = functionSource('
|
|
102
|
+
test('the commit path in runCodeEditorTask separates an edit-requiring block from a transient failure', () => {
|
|
103
|
+
const commitBody = functionSource('runCodeEditorTask');
|
|
104
104
|
assert.match(commitBody, /blockedNeedingEdit/, 'expected the edit-block flag to be set in the prompt');
|
|
105
105
|
assert.match(commitBody, /blockerDetail/, 'expected the verbatim blocker detail to be requested');
|
|
106
106
|
assert.match(
|
|
@@ -115,8 +115,8 @@ test('the commit path in resumeCodeEditorAgent separates an edit-requiring block
|
|
|
115
115
|
);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
test('the commit-recover task in
|
|
119
|
-
const recoverBody = functionSource('
|
|
118
|
+
test('the commit-recover task in runCodeEditorTask is a clean-coder edit step bound to the blocker detail and leaves changes uncommitted', () => {
|
|
119
|
+
const recoverBody = functionSource('runCodeEditorTask');
|
|
120
120
|
assert.match(recoverBody, /agentType:\s*'clean-coder'/, 'expected the fixer to use clean-coder');
|
|
121
121
|
assert.match(recoverBody, /schema:\s*EDIT_SCHEMA/, 'expected the fixer to reuse EDIT_SCHEMA');
|
|
122
122
|
assert.match(recoverBody, /task === 'commit-recover'/, 'expected the commit-recover task branch');
|
|
@@ -161,88 +161,92 @@ test('commitWithRecovery bounds the loop, re-verifies, and retries the commit on
|
|
|
161
161
|
);
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
test('applyFixes routes through
|
|
164
|
+
test('applyFixes routes through the fix-edit task and fixerWithRecovery', () => {
|
|
165
165
|
const applyFixesBody = functionSource('applyFixes');
|
|
166
|
-
assert.match(applyFixesBody, /
|
|
166
|
+
assert.match(applyFixesBody, /runCodeEditorTask\('fix-edit'/, "expected applyFixes to call runCodeEditorTask('fix-edit')");
|
|
167
167
|
assert.match(applyFixesBody, /fixerWithRecovery\(/, 'expected applyFixes to call fixerWithRecovery');
|
|
168
168
|
});
|
|
169
169
|
|
|
170
|
-
test('applyFixes
|
|
170
|
+
test('applyFixes delegates to fixerWithRecovery, which grades fixes with a separate verifier from the fixer', () => {
|
|
171
171
|
const applyFixesBody = functionSource('applyFixes');
|
|
172
172
|
assert.match(
|
|
173
173
|
applyFixesBody,
|
|
174
|
-
/
|
|
175
|
-
'expected applyFixes to
|
|
174
|
+
/fixerWithRecovery\(head, findings, sourceLabel\)/,
|
|
175
|
+
'expected applyFixes to delegate the verify and commit flow to fixerWithRecovery',
|
|
176
176
|
);
|
|
177
|
-
const
|
|
178
|
-
const verifierSpawnIndex = applyFixesBody.search(/spawnVerifierAgent\(/);
|
|
179
|
-
assert.notEqual(fixerSpawnIndex, -1, 'expected applyFixes to spawn the fixer');
|
|
180
|
-
assert.notEqual(verifierSpawnIndex, -1, 'expected applyFixes to spawn the verifier');
|
|
177
|
+
const recoveryBody = functionSource('fixerWithRecovery');
|
|
181
178
|
assert.match(
|
|
182
|
-
|
|
183
|
-
/
|
|
184
|
-
'expected
|
|
179
|
+
recoveryBody,
|
|
180
|
+
/runVerifierTask\('fix-verify'/,
|
|
181
|
+
'expected fixerWithRecovery to grade the fixes with the code-verifier task so the verdict is independent of the fixer',
|
|
182
|
+
);
|
|
183
|
+
assert.match(
|
|
184
|
+
recoveryBody,
|
|
185
|
+
/runFixerTask\('commit'/,
|
|
186
|
+
'expected fixerWithRecovery to commit through the clean-coder fixer task',
|
|
185
187
|
);
|
|
186
188
|
});
|
|
187
189
|
|
|
188
|
-
test('fixerWithRecovery runs verify
|
|
190
|
+
test('fixerWithRecovery runs verify via runVerifierTask and edits/commits via runFixerTask', () => {
|
|
189
191
|
const recoveryBody = functionSource('fixerWithRecovery');
|
|
190
192
|
assert.match(
|
|
191
193
|
recoveryBody,
|
|
192
|
-
/
|
|
193
|
-
'expected fixerWithRecovery to
|
|
194
|
+
/runVerifierTask\('fix-verify'/,
|
|
195
|
+
'expected fixerWithRecovery to run the verify step through the separate verifier task',
|
|
194
196
|
);
|
|
195
197
|
assert.match(
|
|
196
198
|
recoveryBody,
|
|
197
|
-
/
|
|
198
|
-
'expected fixerWithRecovery to
|
|
199
|
+
/runFixerTask\('commit'/,
|
|
200
|
+
'expected fixerWithRecovery to run the commit step through the fixer task',
|
|
199
201
|
);
|
|
200
202
|
assert.doesNotMatch(
|
|
201
203
|
recoveryBody,
|
|
202
|
-
/
|
|
203
|
-
'expected the verify step never to
|
|
204
|
+
/runFixerTask\('(?:verify-commit|fix-verify)'/,
|
|
205
|
+
'expected the verify step never to route through the fixer task — the verifier grades a different agent than the one that edits',
|
|
204
206
|
);
|
|
205
207
|
});
|
|
206
208
|
|
|
207
|
-
test('the fix-path verify
|
|
209
|
+
test('the fix-path verify routes through a different helper and agentType than the fix-path edits, mirroring the repair path', () => {
|
|
208
210
|
const recoveryBody = functionSource('fixerWithRecovery');
|
|
209
|
-
const
|
|
210
|
-
const
|
|
211
|
-
assert.ok(
|
|
212
|
-
assert.ok(
|
|
211
|
+
const verifyHelperMatch = /(\w+)\('fix-verify'/.exec(recoveryBody);
|
|
212
|
+
const editHelperMatch = /(\w+)\('commit'/.exec(recoveryBody);
|
|
213
|
+
assert.ok(verifyHelperMatch, 'expected a verify call naming its task helper');
|
|
214
|
+
assert.ok(editHelperMatch, 'expected an edit/commit call naming its task helper');
|
|
215
|
+
assert.equal(verifyHelperMatch[1], 'runVerifierTask', 'expected verify to route through runVerifierTask (code-verifier)');
|
|
216
|
+
assert.equal(editHelperMatch[1], 'runFixerTask', 'expected commit to route through runFixerTask (clean-coder)');
|
|
213
217
|
assert.notEqual(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
'expected the verify step to
|
|
218
|
+
verifyHelperMatch[1],
|
|
219
|
+
editHelperMatch[1],
|
|
220
|
+
'expected the verify step to route through a different helper than the edit/commit step',
|
|
217
221
|
);
|
|
218
222
|
});
|
|
219
223
|
|
|
220
|
-
test('the verifier carries a fix-verify task so the fix path verdict comes from the verifier
|
|
221
|
-
const verifierBody = functionSource('
|
|
222
|
-
assert.match(verifierBody, /task === 'fix-verify'/, 'expected
|
|
224
|
+
test('the verifier carries a fix-verify task so the fix path verdict comes from the verifier', () => {
|
|
225
|
+
const verifierBody = functionSource('runVerifierTask');
|
|
226
|
+
assert.match(verifierBody, /task === 'fix-verify'/, 'expected runVerifierTask to handle the fix-verify task');
|
|
223
227
|
assert.match(verifierBody, /buildVerdictFenceSteps\(/, 'expected the fix-verify task to emit a verdict fence');
|
|
224
228
|
assert.match(verifierBody, /agentType:\s*'code-verifier'/, 'expected the fix-verify task to run as code-verifier');
|
|
225
229
|
});
|
|
226
230
|
|
|
227
|
-
test('
|
|
228
|
-
const fixerBody = functionSource('
|
|
231
|
+
test('runFixerTask no longer verifies its own edits — no code-verifier verify-commit task remains', () => {
|
|
232
|
+
const fixerBody = functionSource('runFixerTask');
|
|
229
233
|
assert.doesNotMatch(
|
|
230
234
|
fixerBody,
|
|
231
235
|
/task === 'verify-commit'/,
|
|
232
|
-
'expected the fixer to no longer carry the verify-commit task that graded its own
|
|
236
|
+
'expected the fixer to no longer carry the verify-commit task that graded its own edits',
|
|
233
237
|
);
|
|
234
238
|
assert.doesNotMatch(
|
|
235
239
|
fixerBody,
|
|
236
240
|
/agentType:\s*'code-verifier'/,
|
|
237
|
-
'expected the fixer
|
|
241
|
+
'expected the fixer to be clean-coder only — a separate verifier grades the working tree',
|
|
238
242
|
);
|
|
239
243
|
});
|
|
240
244
|
|
|
241
245
|
test('repairConvergence routes its commit through commitWithRecovery wired to the repair-path steps', () => {
|
|
242
246
|
const repairBody = functionSource('repairConvergence');
|
|
243
247
|
assert.match(repairBody, /commitWithRecovery\(/, 'expected repairConvergence to call commitWithRecovery');
|
|
244
|
-
assert.match(repairBody, /
|
|
245
|
-
assert.match(repairBody, /
|
|
248
|
+
assert.match(repairBody, /runCodeEditorTask\(/, 'expected repairConvergence to use runCodeEditorTask');
|
|
249
|
+
assert.match(repairBody, /runVerifierTask\(/, 'expected repairConvergence to use runVerifierTask');
|
|
246
250
|
});
|
|
247
251
|
|
|
248
252
|
test('the round-loop fix-stalled blockers survive the recovery wiring', () => {
|
|
@@ -334,8 +338,8 @@ test('extractVerifyObjection falls back when no finding yields usable text', ()
|
|
|
334
338
|
assert.equal(extractVerifyObjection(transcript), VERIFY_OBJECTION_FALLBACK);
|
|
335
339
|
});
|
|
336
340
|
|
|
337
|
-
test('the verify-recover task in
|
|
338
|
-
const recoverBody = functionSource('
|
|
341
|
+
test('the verify-recover task in runCodeEditorTask is a clean-coder edit step bound to the verifier objection and leaves changes uncommitted', () => {
|
|
342
|
+
const recoverBody = functionSource('runCodeEditorTask');
|
|
339
343
|
assert.match(recoverBody, /agentType:\s*'clean-coder'/, 'expected the fixer to use clean-coder');
|
|
340
344
|
assert.match(recoverBody, /schema:\s*EDIT_SCHEMA/, 'expected the fixer to reuse EDIT_SCHEMA');
|
|
341
345
|
assert.match(recoverBody, /VERIFY-RECOVERY fixer/, 'expected the verify-recovery prompt body');
|
|
@@ -372,12 +376,12 @@ test('verifyWithRecovery bounds the loop, re-fixes on a failed verdict, and re-v
|
|
|
372
376
|
test('applyFixes routes through fixerWithRecovery which handles verify and commit', () => {
|
|
373
377
|
const applyFixesBody = functionSource('applyFixes');
|
|
374
378
|
assert.match(applyFixesBody, /fixerWithRecovery\(/, 'expected applyFixes to call fixerWithRecovery');
|
|
375
|
-
assert.match(applyFixesBody, /
|
|
379
|
+
assert.match(applyFixesBody, /runCodeEditorTask\('fix-edit'/, "expected applyFixes to call runCodeEditorTask('fix-edit')");
|
|
376
380
|
});
|
|
377
381
|
|
|
378
|
-
test('repairConvergence routes its verify through verifyWithRecovery wired to
|
|
382
|
+
test('repairConvergence routes its verify through verifyWithRecovery wired to the task helpers', () => {
|
|
379
383
|
const repairBody = functionSource('repairConvergence');
|
|
380
384
|
assert.match(repairBody, /verifyWithRecovery\(/, 'expected repairConvergence to call verifyWithRecovery');
|
|
381
|
-
assert.match(repairBody, /
|
|
382
|
-
assert.match(repairBody, /
|
|
385
|
+
assert.match(repairBody, /runVerifierTask\(/, 'expected repairConvergence to use runVerifierTask for verify');
|
|
386
|
+
assert.match(repairBody, /runCodeEditorTask\(/, 'expected repairConvergence to use runCodeEditorTask for recover');
|
|
383
387
|
});
|
|
@@ -32,7 +32,7 @@ test('isMergeConflicting reports a conflict only when the check returned conflic
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
test('the git agent handles merge-conflict checks with shell-agnostic polling', () => {
|
|
35
|
-
const gitBody = functionBody('
|
|
35
|
+
const gitBody = functionBody('runGitTask');
|
|
36
36
|
assert.match(gitBody, /mergeable/, 'expected the git agent to read the PR mergeable field');
|
|
37
37
|
assert.match(
|
|
38
38
|
gitBody,
|
|
@@ -43,8 +43,8 @@ test('the git agent handles merge-conflict checks with shell-agnostic polling',
|
|
|
43
43
|
assert.match(gitBody, /sleep 5|Start-Sleep/, 'expected a shell-agnostic poll delay');
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
test('
|
|
47
|
-
const body = functionBody('
|
|
46
|
+
test('runCodeEditorTask conflict-edit path rebases onto origin/main and makes no push', () => {
|
|
47
|
+
const body = functionBody('runCodeEditorTask');
|
|
48
48
|
assert.match(body, /git rebase origin\/main/, 'expected the edit path to rebase onto origin/main');
|
|
49
49
|
assert.match(
|
|
50
50
|
body,
|
|
@@ -55,9 +55,9 @@ test('resumeCodeEditorAgent conflict-edit path rebases onto origin/main and make
|
|
|
55
55
|
|
|
56
56
|
test('resolveMergeConflicts runs check -> edit -> verify -> commit and gates the push on the verdict', () => {
|
|
57
57
|
const body = functionBody('resolveMergeConflicts');
|
|
58
|
-
const checkIndex = body.indexOf("
|
|
59
|
-
const editIndex = body.indexOf(
|
|
60
|
-
const verifyIndex = body.indexOf('
|
|
58
|
+
const checkIndex = body.indexOf("runGitTask('check-merge-conflicts'");
|
|
59
|
+
const editIndex = body.indexOf("runCodeEditorTask('conflict-edit'");
|
|
60
|
+
const verifyIndex = body.indexOf('runVerifierTask(');
|
|
61
61
|
const commitIndex = body.indexOf('commitWithRecovery(');
|
|
62
62
|
assert.notEqual(checkIndex, -1, 'expected the conflict check to run');
|
|
63
63
|
assert.notEqual(editIndex, -1, 'expected the edit step to run');
|