claude-dev-env 1.95.0 → 2.0.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.
- package/_shared/advisor/CLAUDE.md +2 -2
- package/_shared/advisor/advisor-protocol.md +20 -20
- package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +15 -12
- package/_shared/advisor/scripts/model_tier_run_validator.py +11 -10
- package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +25 -19
- package/_shared/advisor/scripts/tests/test_tier_model_ids.py +17 -17
- package/_shared/advisor/scripts/tier_model_ids.py +18 -18
- package/_shared/pr-loop/CLAUDE.md +1 -0
- package/_shared/pr-loop/scripts/CLAUDE.md +2 -1
- package/_shared/pr-loop/scripts/README.md +1 -0
- package/_shared/pr-loop/scripts/code_rules_gate.py +253 -1980
- package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +32 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/__init__.py +7 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/added_line_maps.py +268 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/enforcer_loading.py +172 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_arguments.py +70 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_running.py +326 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/git_blob_readers.py +85 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/git_file_sets.py +331 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_running.py +369 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/conftest.py +14 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_added_line_maps.py +118 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_enforcer_loading.py +17 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_gate_arguments.py +29 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_gate_running.py +99 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_git_blob_readers.py +69 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_git_file_sets.py +137 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_running.py +116 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_violation_scoping.py +75 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_wrapper_plumb_check.py +49 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/violation_scoping.py +328 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/wrapper_plumb_check.py +206 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +24 -17
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/reviews_disabled_constants.py +1 -0
- package/_shared/pr-loop/scripts/reviews_disabled.py +19 -2
- package/_shared/pr-loop/scripts/test_code_rules_gate.py +278 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate_constants.py +6 -39
- package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +43 -0
- package/_shared/pr-loop/worker-spawn.md +186 -0
- package/agents/code-verifier.md +1 -1
- package/bin/ever-shipped-skills.mjs +3 -0
- package/bin/expand_home_directory_tokens.mjs +1 -1
- package/bin/install.mjs +5 -2
- package/hooks/advisory/refactor_guard.py +3 -4
- package/hooks/blocking/CLAUDE.md +7 -1
- package/hooks/blocking/block_main_commit.py +2 -2
- package/hooks/blocking/claude_md_orphan_file_blocker.py +75 -699
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/CLAUDE.md +28 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/__init__.py +1 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/config/__init__.py +1 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/config/orphan_blocker_constants.py +18 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/decision.py +81 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/references.py +307 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/scan_plan.py +124 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/subtree_scan.py +179 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/tests/conftest.py +10 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/tests/test_decision.py +34 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/tests/test_references.py +42 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/tests/test_scan_plan.py +27 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/tests/test_subtree_scan.py +30 -0
- package/hooks/blocking/code_rules_boolean_mustcheck.py +1 -1
- package/hooks/blocking/code_rules_mock_completeness.py +1 -1
- package/hooks/blocking/code_rules_optional_params.py +2 -2
- package/hooks/blocking/code_rules_shared.py +1 -1
- package/hooks/blocking/code_rules_test_assertions.py +1 -1
- package/hooks/blocking/code_rules_typeddict_stub.py +1 -1
- package/hooks/blocking/gh_pr_author_enforcer.py +1 -1
- package/hooks/blocking/inventory_intent_records/CLAUDE.md +26 -0
- package/hooks/blocking/inventory_intent_records/__init__.py +1 -0
- package/hooks/blocking/inventory_intent_records/config/__init__.py +1 -0
- package/hooks/blocking/inventory_intent_records/config/intent_records_constants.py +20 -0
- package/hooks/blocking/inventory_intent_records/records.py +271 -0
- package/hooks/blocking/inventory_intent_records/tests/conftest.py +10 -0
- package/hooks/blocking/inventory_intent_records/tests/test_records.py +80 -0
- package/hooks/blocking/package_inventory_stale_blocker.py +54 -384
- package/hooks/blocking/package_inventory_stale_blocker_parts/CLAUDE.md +26 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/__init__.py +1 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/config/__init__.py +1 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/config/inventory_blocker_constants.py +16 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/decision.py +84 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/inventory_detection.py +307 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/tests/conftest.py +10 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/tests/test_decision.py +38 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/tests/test_inventory_detection.py +61 -0
- package/hooks/blocking/pii_payload_scan.py +138 -42
- package/hooks/blocking/pii_prevention_blocker.py +185 -291
- package/hooks/blocking/pii_prevention_blocker_parts/CLAUDE.md +24 -0
- package/hooks/blocking/pii_prevention_blocker_parts/__init__.py +1 -0
- package/hooks/blocking/pii_prevention_blocker_parts/config/__init__.py +1 -0
- package/hooks/blocking/pii_prevention_blocker_parts/config/repository_resolution_constants.py +28 -0
- package/hooks/blocking/pii_prevention_blocker_parts/repository_exemption.py +214 -0
- package/hooks/blocking/pii_prevention_blocker_parts/repository_resolution.py +208 -0
- package/hooks/blocking/pr_description_command_parser.py +8 -4
- package/hooks/blocking/precommit_code_rules_gate.py +3 -3
- package/hooks/blocking/tdd_enforcer.py +97 -608
- package/hooks/blocking/tdd_enforcer_parts/CLAUDE.md +30 -0
- package/hooks/blocking/tdd_enforcer_parts/__init__.py +1 -0
- package/hooks/blocking/tdd_enforcer_parts/candidate_paths.py +142 -0
- package/hooks/blocking/tdd_enforcer_parts/config/__init__.py +1 -0
- package/hooks/blocking/tdd_enforcer_parts/config/tdd_enforcer_constants.py +32 -0
- package/hooks/blocking/tdd_enforcer_parts/content_analysis.py +268 -0
- package/hooks/blocking/tdd_enforcer_parts/decisions.py +92 -0
- package/hooks/blocking/tdd_enforcer_parts/freshness.py +80 -0
- package/hooks/blocking/tdd_enforcer_parts/git_tracking.py +63 -0
- package/hooks/blocking/tdd_enforcer_parts/path_classification.py +119 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/conftest.py +10 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/test_candidate_paths.py +31 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/test_content_analysis.py +30 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/test_decisions.py +34 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/test_freshness.py +28 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/test_git_tracking.py +48 -0
- package/hooks/blocking/tdd_enforcer_parts/tests/test_path_classification.py +36 -0
- package/hooks/blocking/test_inventory_deadlock_resolution.py +154 -0
- package/hooks/blocking/test_pii_payload_scan.py +168 -0
- package/hooks/blocking/test_tdd_enforcer_restore.py +108 -0
- package/hooks/blocking/test_verifier_verdict_minter.py +55 -158
- package/hooks/blocking/tests/conftest.py +10 -0
- package/hooks/blocking/tests/test_pii_prevention_blocker.py +260 -0
- package/hooks/blocking/tests/test_repository_exemption.py +105 -0
- package/hooks/blocking/tests/test_repository_resolution.py +108 -0
- package/hooks/diagnostic/hook_log_extractor.py +12 -10
- package/hooks/git-hooks/post_commit.py +3 -4
- package/hooks/hooks_constants/CLAUDE.md +2 -2
- package/hooks/hooks_constants/banned_identifiers_constants.py +0 -1
- package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -1
- package/hooks/hooks_constants/local_identity.py +59 -8
- package/hooks/hooks_constants/pii_prevention_constants.py +0 -6
- package/hooks/hooks_constants/test_local_identity.py +105 -3
- package/hooks/pyproject.toml +13 -36
- package/hooks/session/plugin_data_dir_cleanup.py +0 -1
- package/hooks/validation/mypy_validator.py +2 -2
- package/hooks/validators/health_check.py +1 -0
- package/hooks/validators/mypy_integration.py +2 -0
- package/hooks/validators/ruff_integration.py +3 -0
- package/hooks/workflow/auto_formatter.py +5 -4
- package/package.json +1 -1
- package/scripts/CLAUDE.md +4 -0
- package/scripts/dev_env_scripts_constants/CLAUDE.md +6 -4
- package/scripts/dev_env_scripts_constants/code_review_constants.py +71 -0
- package/scripts/dev_env_scripts_constants/grok_worker_constants.py +435 -0
- package/scripts/dev_env_scripts_constants/timing.py +7 -1
- package/scripts/grok_headless_runner.py +294 -0
- package/scripts/grok_worker_preflight.py +410 -0
- package/scripts/invoke_code_review.py +463 -0
- package/scripts/resolve_worker_spawn.py +619 -0
- package/scripts/spawn_grok_batch.py +672 -0
- package/scripts/test_grok_headless_runner.py +626 -0
- package/scripts/test_grok_worker_preflight.py +1054 -0
- package/scripts/test_invoke_code_review.py +672 -0
- package/scripts/test_resolve_worker_spawn.py +1014 -0
- package/scripts/test_spawn_grok_batch.py +1017 -0
- package/skills/CLAUDE.md +5 -3
- package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +72 -13
- package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +121 -14
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +78 -0
- package/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +121 -0
- package/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +196 -6
- package/skills/autoconverge/CLAUDE.md +3 -3
- package/skills/autoconverge/SKILL.md +9 -3
- package/skills/autoconverge/reference/CLAUDE.md +2 -2
- package/skills/autoconverge/reference/convergence.md +33 -11
- package/skills/autoconverge/reference/stop-conditions.md +16 -5
- package/skills/autoconverge/workflow/CLAUDE.md +2 -1
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +7 -2
- package/skills/autoconverge/workflow/converge.codex-gate.test.mjs +300 -0
- package/skills/autoconverge/workflow/converge.contract.test.mjs +5 -5
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +29 -29
- package/skills/autoconverge/workflow/converge.fix-progress.test.mjs +1 -1
- package/skills/autoconverge/workflow/converge.mjs +200 -16
- package/skills/bugteam/CLAUDE.md +2 -2
- package/skills/bugteam/CONSTRAINTS.md +3 -2
- package/skills/bugteam/PROMPTS.md +7 -6
- package/skills/bugteam/SKILL.md +18 -13
- package/skills/bugteam/reference/audit-and-teammates.md +215 -35
- package/skills/bugteam/reference/design-rationale.md +1 -1
- package/skills/bugteam/reference/obstacles/CLAUDE.md +1 -1
- package/skills/bugteam/reference/team-setup.md +8 -2
- package/skills/codex-review/CLAUDE.md +46 -0
- package/skills/codex-review/SKILL.md +181 -0
- package/skills/codex-review/reference/CLAUDE.md +15 -0
- package/skills/codex-review/reference/cli-contract.md +253 -0
- package/skills/codex-review/reference/loop-integration.md +118 -0
- package/skills/codex-review/scripts/codex_down_classifier.py +98 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/CLAUDE.md +18 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/__init__.py +1 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/classifier_constants.py +35 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +86 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/findings_constants.py +18 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/run_constants.py +45 -0
- package/skills/codex-review/scripts/codex_usage_probe.py +573 -0
- package/skills/codex-review/scripts/fixtures/auth_failure_synthetic.txt +1 -0
- package/skills/codex-review/scripts/fixtures/config_load_failure_v0.125.0.txt +1 -0
- package/skills/codex-review/scripts/fixtures/freeform_findings_v0.144.3.txt +6 -0
- package/skills/codex-review/scripts/fixtures/model_rejection_v0.125.0.jsonl +5 -0
- package/skills/codex-review/scripts/fixtures/structured_findings.txt +13 -0
- package/skills/codex-review/scripts/fixtures/success_stream_v0.144.3.jsonl +6 -0
- package/skills/codex-review/scripts/fixtures/unknown_failure_synthetic.txt +1 -0
- package/skills/codex-review/scripts/fixtures/usage_limit_synthetic.txt +1 -0
- package/skills/codex-review/scripts/parse_codex_findings.py +207 -0
- package/skills/codex-review/scripts/run_codex_review.py +415 -0
- package/skills/codex-review/scripts/test_codex_down_classifier.py +143 -0
- package/skills/codex-review/scripts/test_codex_usage_probe.py +678 -0
- package/skills/codex-review/scripts/test_parse_codex_findings.py +130 -0
- package/skills/codex-review/scripts/test_run_codex_review.py +812 -0
- package/skills/codex-review/test_skill_scaffold.py +192 -0
- package/skills/grok-spawn/CLAUDE.md +28 -0
- package/skills/grok-spawn/SKILL.md +226 -0
- package/skills/grok-spawn/reference/flag-profiles.md +132 -0
- package/skills/grok-spawn/reference/worker-briefs.md +152 -0
- package/skills/grokify/SKILL.md +9 -1
- package/skills/grokify/capability-claims.test.mjs +28 -0
- package/skills/grokify/evals/README.md +72 -0
- package/skills/grokify/evals/parse-payload.test.mjs +171 -0
- package/skills/grokify/evals/run-capability-evals.mjs +545 -0
- package/skills/orchestrator/SKILL.md +42 -29
- package/skills/orchestrator-refresh/SKILL.md +17 -9
- package/skills/pr-converge/SKILL.md +34 -13
- package/skills/pr-converge/reference/convergence-gates.md +42 -15
- package/skills/pr-converge/reference/fix-protocol.md +1 -1
- package/skills/pr-converge/reference/ground-rules.md +1 -1
- package/skills/pr-converge/reference/per-tick.md +130 -42
- package/skills/pr-converge/reference/state-schema.md +10 -0
- package/skills/pr-converge/scripts/CLAUDE.md +2 -0
- package/skills/pr-converge/scripts/_pr_converge_path_setup.py +5 -1
- package/skills/pr-converge/scripts/check_convergence.py +605 -29
- package/skills/pr-converge/scripts/check_convergence_availability.py +232 -0
- package/skills/pr-converge/scripts/check_convergence_gates.py +279 -235
- package/skills/pr-converge/scripts/check_convergence_thread_gates.py +1 -1
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +36 -2
- package/skills/pr-converge/scripts/test__pr_converge_path_setup.py +4 -0
- package/skills/pr-converge/scripts/test_check_convergence.py +71 -3
- package/skills/pr-converge/scripts/test_check_convergence_availability.py +326 -0
- package/skills/pr-converge/scripts/test_check_convergence_codex.py +507 -0
- package/skills/pr-converge/scripts/test_check_convergence_contract.py +89 -17
- package/skills/pr-converge/scripts/test_check_convergence_fixture.py +179 -0
- package/skills/pr-converge/scripts/test_check_convergence_gates.py +84 -68
- package/skills/pr-converge/scripts/test_check_convergence_thread_gates.py +24 -0
- package/skills/pr-converge/test_step5_host_branch.py +106 -0
- package/skills/pr-loop-cloud-transport/SKILL.md +2 -0
- package/skills/reviewer-gates/SKILL.md +7 -5
- package/skills/team-advisor/SKILL.md +7 -7
|
@@ -4,7 +4,7 @@ description: >-
|
|
|
4
4
|
Fired by the /orchestrator loop reminder about every 20 minutes to
|
|
5
5
|
re-assert the advisor discipline mid-run: orchestrate, route hard decisions
|
|
6
6
|
to the shared advisor (ENDORSE / CORRECTION / PLAN / STOP — SendMessage on
|
|
7
|
-
Claude, Claude CLI chain on
|
|
7
|
+
Claude, Claude CLI chain on a third-party host), reuse warm agents. Triggers:
|
|
8
8
|
'/orchestrator-refresh'.
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -13,28 +13,36 @@ description: >-
|
|
|
13
13
|
Detect the host profile first (see Host profiles in
|
|
14
14
|
[`_shared/advisor/advisor-protocol.md`](../../_shared/advisor/advisor-protocol.md)).
|
|
15
15
|
Re-assert the discipline for that host only — do not invent an Agent-tool
|
|
16
|
-
Claude `session-advisor` spawn on a
|
|
16
|
+
Claude `session-advisor` spawn on a third-party host.
|
|
17
17
|
|
|
18
|
-
1. **
|
|
18
|
+
1. **Reconcile the task ledger first.** Call `TaskList` before anything else
|
|
19
|
+
this firing. The ledger is stale when any of these holds: a running or
|
|
20
|
+
finished executor has no `in_progress` task naming it as owner; a finished
|
|
21
|
+
executor's task is still open (or was closed without its result merged);
|
|
22
|
+
the next phase you will dispatch has no pending task; a `blockedBy` link
|
|
23
|
+
contradicts the actual run order. Fix every mismatch with TaskCreate /
|
|
24
|
+
TaskUpdate in this same firing — never defer reconciliation to "when the
|
|
25
|
+
agent reports".
|
|
26
|
+
2. **You are the orchestrator.** Orchestrate and hold the user conversation;
|
|
19
27
|
spawn executor subagents to do all the work — every code edit and build or
|
|
20
28
|
test run.
|
|
21
|
-
|
|
29
|
+
3. **Hard decisions go to the shared advisor.**
|
|
22
30
|
- **Claude host:** executors consult the warm `session-advisor` via
|
|
23
31
|
`SendMessage` and receive one of four signals — ENDORSE, CORRECTION, PLAN,
|
|
24
32
|
or STOP. The orchestrating session routes its own hard decisions the same
|
|
25
33
|
way and keeps its tool use to orchestration and light verification reads.
|
|
26
|
-
- **
|
|
34
|
+
- **Third-party host:** the advisor is a max-tier Claude CLI bind owned by this
|
|
27
35
|
session (`claude_chain_runner.py`, Fable high then Opus max). Do **not**
|
|
28
36
|
spawn `session-advisor` via Agent and do **not** tell executors to
|
|
29
37
|
SendMessage a separate advisor agent. Executors report blockers to this
|
|
30
38
|
session; consult the Claude CLI advisor and relay ENDORSE / CORRECTION /
|
|
31
39
|
PLAN / STOP. When the CLI bind is unreachable, fail closed and report to
|
|
32
|
-
the user — do not answer the four signals as this
|
|
33
|
-
|
|
40
|
+
the user — do not answer the four signals as this third-party session.
|
|
41
|
+
4. **Resume before you spawn.** `SendMessage` an existing *executor* agent by
|
|
34
42
|
name or `agentId` to reuse its warm context; prefer that over a cold spawn.
|
|
35
|
-
(On
|
|
43
|
+
(On a third-party host this is executor reuse only — advisor re-bind stays on the CLI
|
|
36
44
|
chain path in the shared protocol.)
|
|
37
|
-
|
|
45
|
+
5. **Fresh spawn only for a genuine task switch.** No tool compacts or clears a
|
|
38
46
|
subagent's context, so a clean context comes from a fresh spawn — never tell
|
|
39
47
|
an agent to compact.
|
|
40
48
|
5. **Re-schedule the next refresh** (about 1200 seconds out) when the loop
|
|
@@ -153,11 +153,12 @@ the `persistent_agents` map
|
|
|
153
153
|
within one bounded wait, drop the map entry, spawn a fresh named agent,
|
|
154
154
|
record it, and continue the tick. Never abort a tick on a stale id;
|
|
155
155
|
never retry the same dead id.
|
|
156
|
-
- **Fresh every round (never persisted):** the Step 5
|
|
157
|
-
pass and the Step 6
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
the named-`code-verifier` entry
|
|
156
|
+
- **Fresh every round (never persisted):** the Step 5 host-aware
|
|
157
|
+
`invoke_code_review.py` / `/code-review high --fix` pass and the Step 6
|
|
158
|
+
bugteam audit (unbiased eyes each round; the enforcer needs the formal
|
|
159
|
+
Skill call), and every `code-verifier` — a named code-verifier never fires
|
|
160
|
+
`SubagentStop`, so no verdict mints (see the named-`code-verifier` entry
|
|
161
|
+
in the Gotchas list below).
|
|
161
162
|
- **Shutdown:** at loop end (convergence or a stop condition), send each
|
|
162
163
|
persistent agent a shutdown request and clear `persistent_agents` before
|
|
163
164
|
the `pr-loop-lifecycle` Close.
|
|
@@ -206,11 +207,11 @@ post a fresh PR in a fresh branch based on origin main to the user.
|
|
|
206
207
|
`pwsh` calls run through the PowerShell tool, not Bash. Bash on
|
|
207
208
|
Windows is Git Bash which cannot execute PowerShell cmdlets. Route all
|
|
208
209
|
PowerShell work through the PowerShell tool or `pwsh -NoProfile -File`.
|
|
209
|
-
- **Cross-repo PR: route cwd into the PR worktree before
|
|
210
|
-
`/code-review high --fix`
|
|
211
|
-
|
|
212
|
-
`EnterWorktree` cannot re-root (it is scoped to the session's
|
|
213
|
-
resolve the PR worktree and `cd` into it per
|
|
210
|
+
- **Cross-repo PR: route cwd into the PR worktree before Step 5 review** —
|
|
211
|
+
`invoke_code_review.py` and `/code-review high --fix` audit the repo of the
|
|
212
|
+
cwd (the helper's `--cwd`). When the session is rooted in a different repo
|
|
213
|
+
than the PR, `EnterWorktree` cannot re-root (it is scoped to the session's
|
|
214
|
+
repo); resolve the PR worktree and `cd` into it per
|
|
214
215
|
[Step 1.5](reference/per-tick.md). Skipping this reviews and edits the
|
|
215
216
|
wrong repo. The route is routine and automatic — never a material fork
|
|
216
217
|
to pause on.
|
|
@@ -292,12 +293,32 @@ round as converged. This rule holds every tick, every loop, every PR.
|
|
|
292
293
|
See: [`reference/per-tick.md` § CODE_REVIEW entry](reference/per-tick.md).
|
|
293
294
|
Pre-condition: cwd is the Step 1.5 PR worktree on `current_head`.
|
|
294
295
|
Scope: FULL `origin/main...HEAD` diff every tick (no path args, no delta cut).
|
|
296
|
+
Review always runs at effort high on model opus through
|
|
297
|
+
`invoke_code_review.py`. Mode decision inputs: host profile + session
|
|
298
|
+
model. Call:
|
|
299
|
+
`python "$HOME/.claude/scripts/invoke_code_review.py" --cwd <PR-worktree>
|
|
300
|
+
--session-model <alias>`. Chain mode uses that cwd and empty stdin; the
|
|
301
|
+
chain process never commits and never pushes. JSON stdout carries
|
|
302
|
+
`mode` (`in_session` | `chain`), `served_command`, `returncode`, and
|
|
303
|
+
`dirty_tree`. Config/host errors still emit that JSON with non-zero
|
|
304
|
+
`returncode` (no traceback-only failure).
|
|
295
305
|
|
|
296
306
|
- [ ] **Static sweep fails** → apply shared fix protocol → push → reset markers
|
|
297
307
|
→ stay CODE_REVIEW → Step 5
|
|
298
|
-
- [ ]
|
|
299
|
-
|
|
300
|
-
- [ ]
|
|
308
|
+
- [ ] **`mode == in_session`** (Claude host, session model opus) → run
|
|
309
|
+
`/code-review high --fix` in-session (no path args)
|
|
310
|
+
- [ ] **`mode == chain`** (any other host or non-opus session) → helper
|
|
311
|
+
already ran the headless review; read `returncode`,
|
|
312
|
+
`served_command`, and `dirty_tree` from JSON
|
|
313
|
+
- [ ] **failed review** (`returncode != 0`, or chain with null
|
|
314
|
+
`served_command`) → do not set `code_review_clean_at` → stay
|
|
315
|
+
CODE_REVIEW → Step 5
|
|
316
|
+
- [ ] **fixes applied** (`dirty_tree` true / working tree dirty) →
|
|
317
|
+
commit + push via shared fix protocol → reset markers → stay
|
|
318
|
+
CODE_REVIEW → Step 5
|
|
319
|
+
- [ ] **clean** (successful serve: `returncode == 0`, chain
|
|
320
|
+
`served_command` non-null when chain, and `dirty_tree` false) →
|
|
321
|
+
zero unresolved threads (else fix + resolve) →
|
|
301
322
|
`code_review_clean_at = current_head` → `phase = BUGTEAM` → Step 6
|
|
302
323
|
|
|
303
324
|
- [ ] **Step 6: BUGTEAM — run, decide, fix, reply, resolve**
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
- [(d) Post-convergence Copilot review request](#d-post-convergence-copilot-review-request)
|
|
9
9
|
- [(e) Thread-resolution gate](#e-thread-resolution-gate)
|
|
10
10
|
- [(f) Mark ready and report](#f-mark-ready-and-report)
|
|
11
|
+
- [(g) Codex review gate (conditional-required)](#g-codex-review-gate-conditional-required)
|
|
11
12
|
Run **only** after the terminal Bugbot gate confirms the HEAD
|
|
12
13
|
(`bugbot_clean_at == current_head` OR `bugbot_down`), which runs just before
|
|
13
14
|
these gates once Step 2 BUGTEAM reports `convergence (zero findings)` with no
|
|
14
15
|
push during the bugteam tick. Gates run in order; first failure determines
|
|
15
|
-
next-tick behavior. Mark PR ready only when
|
|
16
|
+
next-tick behavior. Mark PR ready only when every gate that applies passes.
|
|
16
17
|
|
|
17
18
|
**Mandatory evidence rule:** Every gate that fetches data MUST produce a
|
|
18
19
|
summary of its findings before proceeding to the next gate. Gate (f) MUST
|
|
@@ -47,7 +48,7 @@ Decide (four branches; match first whose predicate holds):
|
|
|
47
48
|
dirty). Apply the shared fix protocol ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md); skill deltas in [`fix-protocol.md`](fix-protocol.md)) in the same tick.
|
|
48
49
|
Reset push-invalidated markers per [ground-rules.md](ground-rules.md) /
|
|
49
50
|
[state-schema.md](state-schema.md) (all `*_clean_at`, `merge_state_status`,
|
|
50
|
-
`bugbot_down`, `bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule
|
|
51
|
+
`bugbot_down`, `bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule
|
|
51
52
|
next wakeup, return. Full back-to-back-clean cycle plus all six gates must
|
|
52
53
|
hold again on new HEAD.
|
|
53
54
|
- **`classification == "dirty"` with empty inline comments matching
|
|
@@ -59,7 +60,7 @@ Decide (four branches; match first whose predicate holds):
|
|
|
59
60
|
new HEAD SHA. Reset push-invalidated markers per
|
|
60
61
|
[ground-rules.md](ground-rules.md) / [state-schema.md](state-schema.md)
|
|
61
62
|
(all `*_clean_at`, `merge_state_status`, `bugbot_down`,
|
|
62
|
-
`bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule next wakeup,
|
|
63
|
+
`bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule next wakeup,
|
|
63
64
|
return. Convergence needs full back-to-back-clean on new HEAD.
|
|
64
65
|
- **`classification == "clean"` (state `APPROVED`):** Set
|
|
65
66
|
`copilot_clean_at = current_head`. Record evidence: "Copilot APPROVED at <SHA>".
|
|
@@ -90,7 +91,7 @@ Decide (four branches; match first whose predicate holds):
|
|
|
90
91
|
path — apply the shared fix protocol ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md); skill deltas in [`fix-protocol.md`](fix-protocol.md)). Reset push-invalidated markers per
|
|
91
92
|
[ground-rules.md](ground-rules.md) / [state-schema.md](state-schema.md)
|
|
92
93
|
(all `*_clean_at`, `merge_state_status`, `bugbot_down`,
|
|
93
|
-
`bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule next wakeup,
|
|
94
|
+
`bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule next wakeup,
|
|
94
95
|
return.
|
|
95
96
|
- **`classification == "dirty"` with empty inline comments matching
|
|
96
97
|
`pull_request_review_id`:** Claude posted findings only in review body
|
|
@@ -99,7 +100,7 @@ Decide (four branches; match first whose predicate holds):
|
|
|
99
100
|
shared fix protocol ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md); skill deltas in [`fix-protocol.md`](fix-protocol.md)). Reset
|
|
100
101
|
push-invalidated markers per [ground-rules.md](ground-rules.md) /
|
|
101
102
|
[state-schema.md](state-schema.md) (all `*_clean_at`, `merge_state_status`,
|
|
102
|
-
`bugbot_down`, `bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule
|
|
103
|
+
`bugbot_down`, `bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule
|
|
103
104
|
next wakeup, return.
|
|
104
105
|
- **`classification == "clean"` (state `APPROVED`):** Record evidence:
|
|
105
106
|
"Claude APPROVED at <SHA>". Continue to gate (c).
|
|
@@ -127,7 +128,7 @@ Persist `mergeable_state` into `merge_state_status`. Decide:
|
|
|
127
128
|
every prior clean state — reset push-invalidated markers per
|
|
128
129
|
[ground-rules.md](ground-rules.md) / [state-schema.md](state-schema.md)
|
|
129
130
|
(all `*_clean_at`, `merge_state_status`, `bugbot_down`,
|
|
130
|
-
`bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule next wakeup,
|
|
131
|
+
`bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule next wakeup,
|
|
131
132
|
return. Loop re-runs from scratch on new HEAD.
|
|
132
133
|
- **`mergeable_state` is `"blocked"`, `"behind"`, `"unknown"`, or `"unstable"` for
|
|
133
134
|
non-conflict reasons** (required checks pending/failing for "unstable",
|
|
@@ -173,7 +174,7 @@ against `current_head`. Decide:
|
|
|
173
174
|
Treat identically to gate (a) dirty path — apply the shared fix protocol ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md); skill deltas in [`fix-protocol.md`](fix-protocol.md)).
|
|
174
175
|
Reset push-invalidated markers per [ground-rules.md](ground-rules.md) /
|
|
175
176
|
[state-schema.md](state-schema.md) (all `*_clean_at`, `merge_state_status`,
|
|
176
|
-
`bugbot_down`, `bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule
|
|
177
|
+
`bugbot_down`, `bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule
|
|
177
178
|
next wakeup, return.
|
|
178
179
|
- **No Copilot review at `current_head` yet:** Record evidence: "No Copilot
|
|
179
180
|
review at <SHA> (wait count: <N>)". Increment `copilot_wait_count`
|
|
@@ -207,7 +208,7 @@ Decide:
|
|
|
207
208
|
shared fix protocol unresolved-thread sweep ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md) step 12; skill deltas in [`fix-protocol.md`](fix-protocol.md)). Push if any code changed → reset
|
|
208
209
|
push-invalidated markers per [ground-rules.md](ground-rules.md) /
|
|
209
210
|
[state-schema.md](state-schema.md) (all `*_clean_at`, `merge_state_status`,
|
|
210
|
-
`bugbot_down`, `bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule
|
|
211
|
+
`bugbot_down`, `bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule
|
|
211
212
|
next wakeup, return. If only resolutions (no code changes), re-check this
|
|
212
213
|
gate without resetting.
|
|
213
214
|
|
|
@@ -218,7 +219,8 @@ Decide:
|
|
|
218
219
|
```
|
|
219
220
|
python $HOME/.claude/skills/pr-converge/scripts/check_convergence.py \
|
|
220
221
|
--owner <O> --repo <R> --pr-number <N> \
|
|
221
|
-
[--bugbot-down] [--copilot-down]
|
|
222
|
+
[--bugbot-down] [--copilot-down] [--codex-down] \
|
|
223
|
+
[--codex-clean-at <SHA>]
|
|
222
224
|
```
|
|
223
225
|
|
|
224
226
|
Ready means exit `0` and the line:
|
|
@@ -233,11 +235,13 @@ Exact printed labels (script order):
|
|
|
233
235
|
2. `bugbot review body clean` (omitted when `bugbot_down`)
|
|
234
236
|
3. `bugteam_clean_at == current_head`
|
|
235
237
|
4. `copilot_clean_at == current_head`
|
|
236
|
-
5. `
|
|
237
|
-
|
|
238
|
-
|
|
238
|
+
5. `codex_clean_at == current_head` (skipped when usage is at/below threshold,
|
|
239
|
+
null, `codex_down`, or the `codex` opt-out token)
|
|
240
|
+
6. `zero unresolved bot threads`
|
|
241
|
+
7. `PR is mergeable`
|
|
242
|
+
8. `no pending requested reviews`
|
|
239
243
|
|
|
240
|
-
On label
|
|
244
|
+
On label 6: `isOutdated == true` excludes the thread; bot filter is login
|
|
241
245
|
substrings `cursor` | `claude` | `copilot` only. The script has no Claude
|
|
242
246
|
APPROVED review gate.
|
|
243
247
|
|
|
@@ -248,7 +252,7 @@ before invoking the script; they never appear as `check_convergence.py` labels.
|
|
|
248
252
|
|
|
249
253
|
When the script fails (exit 1), do NOT mark ready. Report the FAIL label and
|
|
250
254
|
route through the matching fix path (BUGBOT for dirty reviews, rebase for
|
|
251
|
-
merge conflicts, and so on).
|
|
255
|
+
merge conflicts, Codex findings via the shared fix protocol, and so on).
|
|
252
256
|
|
|
253
257
|
When the script passes (exit 0):
|
|
254
258
|
|
|
@@ -258,5 +262,28 @@ Use the `update_pull_request` MCP tool:
|
|
|
258
262
|
|
|
259
263
|
With `state.json`, append convergence row to
|
|
260
264
|
`<TMPDIR>/pr-converge-<session_id>/converged.log` per `multi-pr-orchestration.md` §Memory; else skip.
|
|
261
|
-
Report from the script's PASS lines (the
|
|
265
|
+
Report from the script's PASS lines (the eight labels above). **Omit loop
|
|
262
266
|
pacing** per **Convergence** of active pacing workflow.
|
|
267
|
+
|
|
268
|
+
## (g) Codex review gate (conditional-required)
|
|
269
|
+
|
|
270
|
+
Machine condition label: `codex_clean_at == current_head`.
|
|
271
|
+
|
|
272
|
+
**Threshold rule** (shared with `codex_usage_probe.py` —
|
|
273
|
+
`WEEKLY_USAGE_GATE_THRESHOLD_PERCENT`; never restate the numeric literal):
|
|
274
|
+
|
|
275
|
+
- When the weekly probe reports **more than** the threshold percent left: a
|
|
276
|
+
clean Codex review on `current_head` is required. Stamp
|
|
277
|
+
`codex_clean_at = current_head` after a clean skill run, and pass
|
|
278
|
+
`--codex-clean-at <SHA>` (or keep it in `$CLAUDE_JOB_DIR/pr-converge-state.json`)
|
|
279
|
+
so `check_convergence.py` can verify the stamp.
|
|
280
|
+
- When usage is **at or below** the threshold, or `percent_left` is null: the
|
|
281
|
+
gate is skipped and never blocks ready.
|
|
282
|
+
- When `codex_down == true`, when `CLAUDE_REVIEWS_DISABLED` lists `codex`, or
|
|
283
|
+
when the caller passes `--codex-down`: the gate is bypassed and never blocks.
|
|
284
|
+
|
|
285
|
+
**Agent path before the machine checklist:** run the usage probe, then when
|
|
286
|
+
required and not opted out, invoke the `codex-review` skill against the PR base
|
|
287
|
+
branch (HEAD vs base) per [per-tick.md](per-tick.md). Findings enter the shared
|
|
288
|
+
fix protocol; a `codex_down` classification sets `codex_down = true` and
|
|
289
|
+
continues without blocking.
|
|
@@ -17,7 +17,7 @@ obligations and the same-tick re-entry rule.
|
|
|
17
17
|
- Writes `last_action: "fix_pushed"`, `current_head: <new SHA>`,
|
|
18
18
|
`bugbot_clean_at: null`, `code_review_clean_at: null`,
|
|
19
19
|
`bugteam_clean_at: null`, `copilot_clean_at: null`,
|
|
20
|
-
`merge_state_status: null`, `bugbot_down: false`,
|
|
20
|
+
`merge_state_status: null`, `bugbot_down: false`, `codex_down: false`,
|
|
21
21
|
`phase: "CODE_REVIEW"`, `status: "awaiting_code_review"`, `last_updated`
|
|
22
22
|
(ISO-8601 UTC) to `state.json` (per §Concurrency).
|
|
23
23
|
- Goes idle. Orchestrator spawns a follow-up `general-purpose` agent for the
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
- **Bugbot findings on the current SHA mean fix-then-push-then-re-enter
|
|
8
8
|
CODE_REVIEW,** so the internal passes re-clear the new HEAD before the terminal
|
|
9
9
|
Bugbot gate runs again.
|
|
10
|
-
- **All `*_clean_at`, `merge_state_status`, and `bugbot_down` reset on every push.**
|
|
10
|
+
- **All `*_clean_at`, `merge_state_status`, and `bugbot_down` / `codex_down` reset on every push.**
|
|
11
11
|
- **`bugbot run` comment is load-bearing.** Literal phrase exactly —
|
|
12
12
|
empirically the only re-trigger Cursor Bugbot recognizes.
|
|
13
13
|
- **Production edits go through `clean-coder`, except `/code-review high --fix`.**
|
|
@@ -53,8 +53,8 @@ pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get") → `
|
|
|
53
53
|
If owner/repo/number are not yet known, extract them from the PR URL.
|
|
54
54
|
If `current_head` changed since last tick, reset push-invalidated markers
|
|
55
55
|
per [ground-rules.md](ground-rules.md) / [state-schema.md](state-schema.md)
|
|
56
|
-
(all `*_clean_at`, `merge_state_status`, `bugbot_down`, `bugbot_acknowledged_at
|
|
57
|
-
new HEAD invalidates prior clean and down-detection state.
|
|
56
|
+
(all `*_clean_at`, `merge_state_status`, `bugbot_down`, `bugbot_acknowledged_at`,
|
|
57
|
+
`codex_down`) — new HEAD invalidates prior clean and down-detection state.
|
|
58
58
|
|
|
59
59
|
Capture `number`, `head.sha` (= `current_head`), owner/repo, branch.
|
|
60
60
|
|
|
@@ -171,9 +171,10 @@ CODE_REVIEW.
|
|
|
171
171
|
### `phase == CODE_REVIEW`
|
|
172
172
|
|
|
173
173
|
The entry phase of every convergence tick, re-entered after any fix push. It runs
|
|
174
|
-
a deterministic static sweep, then
|
|
175
|
-
|
|
176
|
-
review artifact, so there are no code-review threads to
|
|
174
|
+
a deterministic static sweep, then the built-in `/code-review high --fix` on the
|
|
175
|
+
full `origin/main...HEAD` diff at effort high on model opus. `/code-review`
|
|
176
|
+
produces no GitHub review artifact, so there are no code-review threads to
|
|
177
|
+
resolve.
|
|
177
178
|
|
|
178
179
|
a. **Static sweep — runs first, before `/code-review`.** Run the deterministic
|
|
179
180
|
gates over the full `origin/main...HEAD` changed files:
|
|
@@ -182,41 +183,85 @@ a. **Static sweep — runs first, before `/code-review`.** Run the deterministic
|
|
|
182
183
|
shared fix protocol ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md); skill deltas in [`fix-protocol.md`](fix-protocol.md)), commit and push,
|
|
183
184
|
reset push-invalidated markers per [ground-rules.md](ground-rules.md) /
|
|
184
185
|
[state-schema.md](state-schema.md) (all `*_clean_at`, `merge_state_status`,
|
|
185
|
-
`bugbot_down`, `bugbot_acknowledged_at`), stay
|
|
186
|
-
re-run the sweep. When the sweep is clean, run
|
|
186
|
+
`bugbot_down`, `bugbot_acknowledged_at`, `codex_down`), stay
|
|
187
|
+
`phase = CODE_REVIEW`, and re-run the sweep. When the sweep is clean, run
|
|
188
|
+
the host-aware review below.
|
|
187
189
|
|
|
188
|
-
b. Run
|
|
189
|
-
|
|
190
|
+
b. Run the built-in `/code-review high --fix` on the FULL `origin/main...HEAD`
|
|
191
|
+
diff — every file the PR touches — via the
|
|
190
192
|
[local diff review](https://code.claude.com/docs/en/code-review#review-a-diff-locally).
|
|
191
|
-
|
|
193
|
+
The review always runs at effort high on model opus. It reviews the diff and
|
|
194
|
+
applies its findings to the working tree.
|
|
192
195
|
|
|
193
196
|
Before running, confirm the working directory is the PR worktree resolved
|
|
194
197
|
in [Step 1.5](#step-15-resolve-the-pr-worktree-cwd-routing) — `git rev-parse
|
|
195
198
|
--show-toplevel` is that checkout and `git rev-parse HEAD` equals
|
|
196
199
|
`current_head` — with no uncommitted edits. When the session is rooted in a
|
|
197
200
|
different repo than the PR, the `cd` from Step 1.5 supplies this; the
|
|
198
|
-
persisted working directory is
|
|
199
|
-
`/code-review high --fix` with no path arguments so it audits the whole branch
|
|
200
|
-
diff against `origin/main`. Do not delta-scope to commits added since the
|
|
201
|
-
prior clean SHA, do not scope to a single file, do not scope to bugbot's
|
|
202
|
-
flagged paths. A partial-scope round does not count and cannot set
|
|
203
|
-
`code_review_clean_at`. Invoke `/code-review high --fix` so the pre-catch pass
|
|
204
|
-
gets broad coverage regardless of the session's current effort.
|
|
201
|
+
persisted working directory is the cwd the review audits.
|
|
205
202
|
|
|
206
|
-
|
|
203
|
+
Route every CODE_REVIEW pass through the host-aware helper
|
|
204
|
+
`invoke_code_review.py`. Mode decision inputs are the host profile (detected
|
|
205
|
+
by the helper) and the caller's session model short alias:
|
|
207
206
|
|
|
208
|
-
|
|
207
|
+
```bash
|
|
208
|
+
python "$HOME/.claude/scripts/invoke_code_review.py" \
|
|
209
|
+
--cwd "$(git rev-parse --show-toplevel)" \
|
|
210
|
+
--session-model <session-model-alias>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The helper prints one JSON object on stdout only:
|
|
214
|
+
`{mode, served_command, returncode, dirty_tree}`. Chain mode sets cwd to the
|
|
215
|
+
PR worktree and redirects stdin from the empty stream so the spawn does not
|
|
216
|
+
wait for interactive input. The chain process never commits and never pushes
|
|
217
|
+
— commit and push belong to this step via the shared fix protocol. On
|
|
218
|
+
`ChainConfigurationError` or host `ValueError`, the helper still prints that
|
|
219
|
+
JSON shape (non-zero `returncode`, null `served_command`) and exits non-zero
|
|
220
|
+
— never a traceback-only failure.
|
|
221
|
+
|
|
222
|
+
Match the first mode whose predicate holds:
|
|
223
|
+
|
|
224
|
+
- **`mode == "in_session"`** (Claude host and session model is opus): run
|
|
225
|
+
`/code-review high --fix` in this session with no path arguments so it
|
|
226
|
+
audits the whole branch diff against `origin/main`. After it returns, a
|
|
227
|
+
non-empty `git status --porcelain` means fixes applied (`dirty_tree`
|
|
228
|
+
equivalent). Treat a failed in-session slash command the same as a failed
|
|
229
|
+
review: do not set `code_review_clean_at`.
|
|
230
|
+
- **`mode == "chain"`** (any other host, or a Claude session on any model
|
|
231
|
+
other than opus): the helper already ran the headless review
|
|
232
|
+
(`claude -p "/code-review high --fix" --model opus` through the chain
|
|
233
|
+
runner) with cwd set to the PR worktree. Read `returncode`,
|
|
234
|
+
`served_command`, and `dirty_tree` from the JSON. A successful serve is
|
|
235
|
+
`returncode == 0` with a non-null `served_command`. `dirty_tree` true
|
|
236
|
+
means fixes applied; `dirty_tree` false is clean only after a successful
|
|
237
|
+
serve.
|
|
238
|
+
|
|
239
|
+
Do not delta-scope to commits added since the prior clean SHA, do not scope
|
|
240
|
+
to a single file, do not scope to bugbot's flagged paths. A partial-scope
|
|
241
|
+
round does not count and cannot set `code_review_clean_at`.
|
|
242
|
+
|
|
243
|
+
c. Decide (three branches; match first whose predicate holds):
|
|
244
|
+
|
|
245
|
+
- **Failed review (`returncode != 0`, or chain mode with null
|
|
246
|
+
`served_command`):** The review did not complete a successful serve. Do
|
|
247
|
+
not set `code_review_clean_at`. Stay `phase = CODE_REVIEW`, schedule next
|
|
248
|
+
wakeup, return. A failed chain often leaves `dirty_tree` false — that is
|
|
249
|
+
not a clean stamp.
|
|
250
|
+
- **Fixes applied (working tree dirty / `dirty_tree` true):** Commit the
|
|
209
251
|
applied fixes in one commit → push, following the shared fix protocol
|
|
210
252
|
commit and push steps ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md)). Reset
|
|
211
253
|
push-invalidated markers per [ground-rules.md](ground-rules.md) /
|
|
212
254
|
[state-schema.md](state-schema.md) (all `*_clean_at`, `merge_state_status`,
|
|
213
|
-
`bugbot_down`, `bugbot_acknowledged_at`). Stay
|
|
214
|
-
schedule next wakeup, return. Every fix push
|
|
215
|
-
passes on the new HEAD.
|
|
216
|
-
- **Clean (
|
|
255
|
+
`bugbot_down`, `bugbot_acknowledged_at`, `codex_down`). Stay
|
|
256
|
+
`phase = CODE_REVIEW`, schedule next wakeup, return. Every fix push
|
|
257
|
+
re-enters the internal passes on the new HEAD.
|
|
258
|
+
- **Clean (successful serve: `returncode == 0`, chain `served_command`
|
|
259
|
+
non-null when `mode == chain`, and `dirty_tree` false):** Set
|
|
217
260
|
`code_review_clean_at = current_head`, `phase = BUGTEAM`. Continue
|
|
218
261
|
BUGTEAM in same tick — back-to-back convergence requires code-review and
|
|
219
|
-
bugteam clean on the same HEAD before the terminal gates run.
|
|
262
|
+
bugteam clean on the same HEAD before the terminal gates run. Helper
|
|
263
|
+
contract: `is_code_review_clean_stamp_allowed` is true only for this
|
|
264
|
+
branch.
|
|
220
265
|
|
|
221
266
|
### `phase == BUGTEAM`
|
|
222
267
|
|
|
@@ -263,8 +308,8 @@ pushed commits during its run. `current_head` from Step 1 is stale:
|
|
|
263
308
|
If `new_head != current_head`, set `current_head = new_head` and reset
|
|
264
309
|
push-invalidated markers per [ground-rules.md](ground-rules.md) /
|
|
265
310
|
[state-schema.md](state-schema.md) (all `*_clean_at`, `merge_state_status`,
|
|
266
|
-
`bugbot_down`, `bugbot_acknowledged_at`). New commits
|
|
267
|
-
clean and down-detection state.
|
|
311
|
+
`bugbot_down`, `bugbot_acknowledged_at`, `codex_down`). New commits
|
|
312
|
+
invalidate prior clean and down-detection state.
|
|
268
313
|
|
|
269
314
|
c. Inspect bugteam outcome. Reports `convergence (zero findings)` or list
|
|
270
315
|
of unfixed findings with file:line.
|
|
@@ -283,8 +328,8 @@ never falsely terminates:
|
|
|
283
328
|
([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md); skill deltas in [fix-protocol.md](fix-protocol.md)). Reset push-invalidated markers
|
|
284
329
|
per [ground-rules.md](ground-rules.md) / [state-schema.md](state-schema.md)
|
|
285
330
|
(all `*_clean_at`, `merge_state_status`, `bugbot_down`,
|
|
286
|
-
`bugbot_acknowledged_at`), `phase = CODE_REVIEW`, schedule
|
|
287
|
-
return.
|
|
331
|
+
`bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`, schedule
|
|
332
|
+
next wakeup, return.
|
|
288
333
|
|
|
289
334
|
### `phase == BUGBOT` (terminal gate)
|
|
290
335
|
|
|
@@ -295,8 +340,9 @@ passes are clean; Bugbot confirms the HEAD, then the convergence gates run.
|
|
|
295
340
|
`python "$HOME/.claude/_shared/pr-loop/scripts/reviews_disabled.py" --reviewer bugbot`
|
|
296
341
|
|
|
297
342
|
- Exit 0 (Bugbot disabled for this run — the default, unless
|
|
298
|
-
`CLAUDE_REVIEWS_ENABLED` lists `bugbot`) → set `bugbot_down = true`,
|
|
299
|
-
|
|
343
|
+
`CLAUDE_REVIEWS_ENABLED` lists `bugbot`) → set `bugbot_down = true`, run the
|
|
344
|
+
[Codex review step](#codex-review-step-conditional), advance to the
|
|
345
|
+
[convergence gates](convergence-gates.md) in the same tick with the Bugbot
|
|
300
346
|
gate bypassed; skip steps a–c below.
|
|
301
347
|
- Exit 1 (`CLAUDE_REVIEWS_ENABLED` lists `bugbot` and `CLAUDE_REVIEWS_DISABLED`
|
|
302
348
|
does not) → go to step a.
|
|
@@ -344,18 +390,19 @@ c. Decide (four branches; match first whose predicate holds):
|
|
|
344
390
|
Bugbot gate next tick.
|
|
345
391
|
- **`commit_id == current_head` AND zero unaddressed inline AND review
|
|
346
392
|
body clean:** Set `bugbot_clean_at = current_head`, reset
|
|
347
|
-
`inline_lag_streak = 0`,
|
|
348
|
-
gates](convergence-gates.md) in the same
|
|
393
|
+
`inline_lag_streak = 0`, run the [Codex review step](#codex-review-step-conditional)
|
|
394
|
+
then advance to the [convergence gates](convergence-gates.md) in the same
|
|
395
|
+
tick.
|
|
349
396
|
- **`commit_id == current_head` with unaddressed inline findings:**
|
|
350
397
|
Apply the shared fix protocol ([`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md); skill deltas in [`fix-protocol.md`](fix-protocol.md)).
|
|
351
398
|
Reset `inline_lag_streak = 0` and push-invalidated markers per
|
|
352
399
|
[ground-rules.md](ground-rules.md) / [state-schema.md](state-schema.md)
|
|
353
400
|
(all `*_clean_at`, `merge_state_status`, `bugbot_down`,
|
|
354
|
-
`bugbot_acknowledged_at`), `phase = CODE_REVIEW`. With
|
|
355
|
-
clean-coder teammate executes the fix, writes
|
|
356
|
-
next tick re-enters CODE_REVIEW on the new
|
|
357
|
-
(single-PR): the lead executes it, stays
|
|
358
|
-
next wakeup, return.
|
|
401
|
+
`bugbot_acknowledged_at`, `codex_down`), `phase = CODE_REVIEW`. With
|
|
402
|
+
`state.json`: the clean-coder teammate executes the fix, writes
|
|
403
|
+
`state.json`, goes idle; the next tick re-enters CODE_REVIEW on the new
|
|
404
|
+
HEAD. No `state.json` (single-PR): the lead executes it, stays
|
|
405
|
+
`phase = CODE_REVIEW`. Schedule next wakeup, return.
|
|
359
406
|
|
|
360
407
|
### `phase == COPILOT_WAIT`
|
|
361
408
|
|
|
@@ -386,9 +433,9 @@ b. Decide (three branches; match first whose predicate holds):
|
|
|
386
433
|
no inline threads. Reset push-invalidated markers per
|
|
387
434
|
[ground-rules.md](ground-rules.md) / [state-schema.md](state-schema.md)
|
|
388
435
|
(all `*_clean_at`, `merge_state_status`, `bugbot_down`,
|
|
389
|
-
`bugbot_acknowledged_at`). **Set `phase = CODE_REVIEW`**
|
|
390
|
-
— every fix push re-enters the internal passes on the
|
|
391
|
-
next wakeup, return.
|
|
436
|
+
`bugbot_acknowledged_at`, `codex_down`). **Set `phase = CODE_REVIEW`**
|
|
437
|
+
(NOT COPILOT_WAIT) — every fix push re-enters the internal passes on the
|
|
438
|
+
new HEAD. Schedule next wakeup, return.
|
|
392
439
|
- **No Copilot review at `current_head` yet:** Increment
|
|
393
440
|
`copilot_wait_count` (init 0 on COPILOT_WAIT entry; reset to 0 on
|
|
394
441
|
every push and on every successful Copilot review). `>= 3` → hard
|
|
@@ -401,6 +448,43 @@ back-to-back-clean guarantee (the internal code-review and bugteam passes both
|
|
|
401
448
|
clean on the same HEAD before the terminal gates re-open) only holds when every
|
|
402
449
|
fix commit re-enters through CODE_REVIEW.
|
|
403
450
|
|
|
451
|
+
## Codex review step (conditional)
|
|
452
|
+
|
|
453
|
+
Run once the terminal Bugbot gate has confirmed HEAD (or set `bugbot_down`) and
|
|
454
|
+
**before** the [convergence gates](convergence-gates.md) machine checklist.
|
|
455
|
+
Uses the `codex-review` skill wrapper against the PR **base** branch (HEAD vs
|
|
456
|
+
base), never an invented commit range.
|
|
457
|
+
|
|
458
|
+
1. **Opt-out / down gate.**
|
|
459
|
+
`python "$HOME/.claude/_shared/pr-loop/scripts/reviews_disabled.py" --reviewer codex`
|
|
460
|
+
- Exit 0 → set `codex_down = true`, skip the skill, continue to convergence
|
|
461
|
+
gates (export `CLAUDE_REVIEWS_DISABLED` including `codex` before the
|
|
462
|
+
checklist so `check_convergence.py` bypasses without flags).
|
|
463
|
+
- Exit 1 → continue.
|
|
464
|
+
|
|
465
|
+
2. **Usage probe.**
|
|
466
|
+
`python "$HOME/.claude/skills/codex-review/scripts/codex_usage_probe.py"`
|
|
467
|
+
- When `percent_left` is null or not strictly above the probe threshold
|
|
468
|
+
constant (`WEEKLY_USAGE_GATE_THRESHOLD_PERCENT`): skip Codex; do not set
|
|
469
|
+
`codex_clean_at`; continue to convergence gates (the machine checklist
|
|
470
|
+
skips the condition on the same rule).
|
|
471
|
+
- When above threshold: continue to the skill.
|
|
472
|
+
|
|
473
|
+
3. **Skill wrapper (HEAD vs base).** Invoke `codex-review` (or read
|
|
474
|
+
`../../codex-review/SKILL.md` when `Skill` is not invokable) so the wrapper
|
|
475
|
+
reviews the diff against the PR base branch at `current_head`.
|
|
476
|
+
|
|
477
|
+
4. **Classify.**
|
|
478
|
+
- `clean` → set `codex_clean_at = current_head`; write the stamp into
|
|
479
|
+
`$CLAUDE_JOB_DIR/pr-converge-state.json` (and pass `--codex-clean-at` into
|
|
480
|
+
`check_convergence.py` when invoking the checklist).
|
|
481
|
+
- `findings` → apply the shared fix protocol; reset push-invalidated markers
|
|
482
|
+
(all `*_clean_at`, `merge_state_status`, `bugbot_down`,
|
|
483
|
+
`bugbot_acknowledged_at`, `codex_down`); `phase = CODE_REVIEW`; schedule
|
|
484
|
+
next wakeup; return.
|
|
485
|
+
- `down` / `codex_down` → set `codex_down = true`; continue to convergence
|
|
486
|
+
gates without blocking ready.
|
|
487
|
+
|
|
404
488
|
## Step 3: Re-trigger bugbot
|
|
405
489
|
|
|
406
490
|
- [ ] **Availability gate.** Enforced at BUGBOT entry (see `### phase == BUGBOT`).
|
|
@@ -413,10 +497,14 @@ fix commit re-enters through CODE_REVIEW.
|
|
|
413
497
|
(`../../reviewer-gates/SKILL.md` § Gate 3) against `current_head` — the
|
|
414
498
|
silent-pass pre-check, the already-queued check, the trigger comment, and
|
|
415
499
|
the acknowledge check, with their rationale. Map its outcomes:
|
|
416
|
-
- [ ] Silent pass → set `bugbot_clean_at = current_head`,
|
|
500
|
+
- [ ] Silent pass → set `bugbot_clean_at = current_head`, run the
|
|
501
|
+
[Codex review step](#codex-review-step-conditional), advance to the
|
|
502
|
+
[convergence gates](convergence-gates.md) same tick
|
|
417
503
|
- [ ] Already queued → skip posting, wait for completion, advance to Step 4
|
|
418
504
|
- [ ] Trigger acknowledged (`bugbot_acknowledged_at` recorded) → advance to Step 4
|
|
419
|
-
- [ ] Bugbot down → set `bugbot_down = true`,
|
|
505
|
+
- [ ] Bugbot down → set `bugbot_down = true`, run the
|
|
506
|
+
[Codex review step](#codex-review-step-conditional), advance to the
|
|
507
|
+
[convergence gates](convergence-gates.md) same tick
|
|
420
508
|
|
|
421
509
|
## Step 4: Loop pacing
|
|
422
510
|
|
|
@@ -33,6 +33,16 @@ live ONLY in the single-PR `$CLAUDE_JOB_DIR/pr-converge-state.json` file
|
|
|
33
33
|
Reset to `null` on every push.
|
|
34
34
|
- `copilot_clean_at`: HEAD SHA where Copilot last reported clean, or `null`.
|
|
35
35
|
Reset to `null` on every push.
|
|
36
|
+
- `codex_clean_at`: HEAD SHA where the Codex review skill last reported clean,
|
|
37
|
+
or `null`. Reset to `null` on every push. The machine checklist requires this
|
|
38
|
+
stamp to equal `current_head` only when weekly usage is above the probe
|
|
39
|
+
threshold (see [convergence-gates.md](convergence-gates.md)).
|
|
40
|
+
- `codex_down`: boolean, init `false`. Set `true` when the Codex skill
|
|
41
|
+
classifies `codex_down`, when `CLAUDE_REVIEWS_DISABLED` lists `codex`, or when
|
|
42
|
+
the agent passes `--codex-down` into `check_convergence.py`. While `true`,
|
|
43
|
+
the Codex gate never blocks ready. Reset to `false` on every push (same
|
|
44
|
+
push-invalidation rule as `bugbot_down`); the availability / opt-out check
|
|
45
|
+
re-applies on the next Codex entry.
|
|
36
46
|
- `merge_state_status`: last-observed `mergeable_state` from
|
|
37
47
|
`pull_request_read(method="get")` (e.g. `clean`, `dirty`, `blocked`,
|
|
38
48
|
`behind`, `unknown`, `unstable`), or `null` before the first check. Reset
|
|
@@ -8,6 +8,7 @@ Python helper scripts for the `pr-converge` skill, plus their tests and a PowerS
|
|
|
8
8
|
|---|---|
|
|
9
9
|
| `check_bugbot_ci.py` | Checks bugbot CI check-run status on a given SHA |
|
|
10
10
|
| `check_convergence.py` | Evaluates whether all convergence gates pass on the current HEAD |
|
|
11
|
+
| `check_convergence_availability.py` | Resolves reviewer waivers from flag, disk-authoritative settings (env fallback), and the availability/quota probe, with waived / enforced / probe_error_reason states |
|
|
11
12
|
| `check_convergence_gates.py` | GitHub REST leaf checks (review and Bugbot) the convergence gates call |
|
|
12
13
|
| `check_convergence_thread_gates.py` | GitHub GraphQL and REST leaf checks (review threads and pending reviewers) the convergence gates call |
|
|
13
14
|
| `check_pending_reviews.py` | Fetches pending review requests and reviewer states |
|
|
@@ -19,6 +20,7 @@ Python helper scripts for the `pr-converge` skill, plus their tests and a PowerS
|
|
|
19
20
|
| `conftest.py` | Puts the scripts directory on `sys.path` so pytest collects the suite |
|
|
20
21
|
| `test_check_bugbot_ci.py` | Tests for `check_bugbot_ci.py` |
|
|
21
22
|
| `test_check_convergence.py` | Tests for `check_convergence.py` |
|
|
23
|
+
| `test_check_convergence_availability.py` | Tests for `check_convergence_availability.py` |
|
|
22
24
|
| `test_check_convergence_contract.py` | Contract pins for `check_convergence.py` gate wiring |
|
|
23
25
|
| `test_check_convergence_gates.py` | Tests for `check_convergence_gates.py` |
|
|
24
26
|
| `test_check_convergence_thread_gates.py` | Tests for `check_convergence_thread_gates.py` |
|
|
@@ -10,10 +10,12 @@ from pathlib import Path
|
|
|
10
10
|
|
|
11
11
|
_scripts_directory = Path(__file__).resolve().parent
|
|
12
12
|
_skill_directory = _scripts_directory.parent
|
|
13
|
-
|
|
13
|
+
_skills_directory = _skill_directory.parent
|
|
14
|
+
_claude_dev_env_directory = _skills_directory.parent
|
|
14
15
|
_shared_pr_loop_scripts_directory = (
|
|
15
16
|
_claude_dev_env_directory / "_shared" / "pr-loop" / "scripts"
|
|
16
17
|
)
|
|
18
|
+
_codex_review_scripts_directory = _skills_directory / "codex-review" / "scripts"
|
|
17
19
|
|
|
18
20
|
if str(_scripts_directory) not in sys.path:
|
|
19
21
|
sys.path.insert(0, str(_scripts_directory))
|
|
@@ -21,3 +23,5 @@ if str(_skill_directory) not in sys.path:
|
|
|
21
23
|
sys.path.insert(0, str(_skill_directory))
|
|
22
24
|
if str(_shared_pr_loop_scripts_directory) not in sys.path:
|
|
23
25
|
sys.path.insert(0, str(_shared_pr_loop_scripts_directory))
|
|
26
|
+
if str(_codex_review_scripts_directory) not in sys.path:
|
|
27
|
+
sys.path.insert(0, str(_codex_review_scripts_directory))
|