claude-dev-env 2.15.1 → 2.17.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/.agents/agents/.claude/CLAUDE.md +1 -0
- package/{agents → .agents/agents}/AGENTS.md +8 -2
- package/{agents → .agents/agents}/test_agent_frontmatter.py +1 -1
- package/.agents/skills/.claude/CLAUDE.md +1 -0
- package/.agents/skills/AGENTS.md +71 -0
- package/.agents/skills/_shared/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/_shared/AGENTS.md +2 -2
- package/.agents/skills/_shared/advisor/.claude/CLAUDE.md +1 -0
- package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/_shared/pr-loop/AGENTS.md +22 -15
- package/{skills → .agents/skills}/_shared/pr-loop/portable-driver.md +6 -7
- package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +1 -0
- package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +9 -0
- package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/_shared/pr-loop/scripts/AGENTS.md +1 -1
- package/{skills → .agents/skills}/_shared/pr-loop/scripts/portable_converge_driver.py +25 -16
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +6 -1
- package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +1 -5
- package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_build_audit_prompt.py +9 -3
- package/{skills → .agents/skills}/_shared/pr-loop/scripts/write_audit_outcomes.py +1 -1
- package/{skills → .agents/skills}/_shared/pr-loop/scripts/write_fix_outcomes.py +1 -1
- package/.agents/skills/autoconverge/.claude/CLAUDE.md +1 -0
- package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +1 -0
- package/.agents/skills/autoconverge/reference/convergence-gates.md +31 -0
- package/{skills → .agents/skills}/autoconverge/reference/convergence.md +8 -10
- package/{skills → .agents/skills}/autoconverge/reference/gotchas.md +1 -1
- package/{skills → .agents/skills}/autoconverge/reference/stop-conditions.md +1 -1
- package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +1 -0
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/autoconverge/workflow/converge.codex-gate.test.mjs +1 -1
- package/{skills → .agents/skills}/autoconverge/workflow/converge.contract.test.mjs +1 -1
- package/{skills → .agents/skills}/autoconverge/workflow/converge.mjs +3 -3
- package/.agents/skills/cert-classification-rule/SKILL.md +224 -0
- package/.agents/skills/cert-classification-rule/scripts/resort_cert_folders.py +158 -0
- package/{skills → .agents/skills}/e-code-review/reference/effort-evaluation.md +1 -1
- package/.agents/skills/eli5/SKILL.md +128 -0
- package/.agents/skills/eli5/reference/task-seeds.md +11 -0
- package/.agents/skills/everything-search/.claude/CLAUDE.md +1 -0
- package/.agents/skills/fresh-branch/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/fresh-branch/scripts/test_create_fresh_branch.py +2 -3
- package/.agents/skills/grok-spawn/.claude/CLAUDE.md +1 -0
- package/.agents/skills/name-by-capability-audit/SKILL.md +67 -0
- package/.agents/skills/name-by-capability-audit/reference/fetch-commands.md +29 -0
- package/.agents/skills/name-by-capability-audit/reference/offense-examples.md +32 -0
- package/.agents/skills/name-by-capability-audit/reference/report-template.md +29 -0
- package/.agents/skills/name-by-capability-audit/reference/rule-checklist.md +38 -0
- package/.agents/skills/name-by-capability-audit/reference/task-seeds.md +9 -0
- package/.agents/skills/pr-cleanup/SKILL.md +99 -0
- package/{skills → .agents/skills}/prototype/reference/honest-limitations.md +1 -1
- package/{skills → .agents/skills}/prototype/reference/promotion-tasks.md +1 -1
- package/{skills → .agents/skills}/prototype/scripts/test_build_sandbox_settings.py +2 -2
- package/{skills → .agents/skills}/prototype/scripts/test_probe_sandbox_safety.py +1 -1
- package/{skills → .agents/skills}/prototype/workflows/promotion.md +2 -2
- package/.agents/skills/rebase/.claude/CLAUDE.md +1 -0
- package/.agents/skills/review-router/SKILL.md +51 -0
- package/.agents/skills/review-router/reference/route-policy.json +7 -0
- package/.agents/skills/review-router/reference/task-seeds.md +1 -0
- package/.agents/skills/review-router/scripts/conftest.py +4 -0
- package/.agents/skills/review-router/scripts/review_router.py +50 -0
- package/.agents/skills/review-router/scripts/review_router_cli.py +211 -0
- package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +1 -0
- package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
- package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +13 -0
- package/.agents/skills/review-router/scripts/test_review_router.py +23 -0
- package/.agents/skills/review-router/scripts/test_review_router_cli.py +47 -0
- package/.agents/skills/review-tier/SKILL.md +56 -0
- package/.agents/skills/review-tier/reference/task-seeds.md +1 -0
- package/.agents/skills/review-tier/reference/tier-policy.json +9 -0
- package/.agents/skills/review-tier/scripts/conftest.py +4 -0
- package/.agents/skills/review-tier/scripts/review_tier.py +332 -0
- package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +1 -0
- package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
- package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +29 -0
- package/.agents/skills/review-tier/scripts/test_generation.py +171 -0
- package/.agents/skills/review-tier/scripts/test_review_tier.py +33 -0
- package/.agents/skills/run-claude-dev-env/SKILL.md +84 -0
- package/.agents/skills/run-claude-dev-env/driver.mjs +239 -0
- package/.agents/skills/session-log/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/session-log/SKILL.md +1 -1
- package/.agents/skills/session-tidy/.claude/CLAUDE.md +1 -0
- package/.agents/skills/shared-extraction-audit/SKILL.md +160 -0
- package/.agents/skills/shared-extraction-audit/reference/examples.md +46 -0
- package/.agents/skills/shared-extraction-audit/reference/offense-taxonomy.md +100 -0
- package/.agents/skills/skill-builder/.claude/CLAUDE.md +1 -0
- package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills}/skill-builder/references/deterministic-elements.md +1 -1
- package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +1 -0
- package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +1 -0
- package/.agents/skills/source-command-logifix/SKILL.md +29 -0
- package/.agents/skills/source-command-sr-loop/SKILL.md +58 -0
- package/.agents/skills/task-build/.claude/CLAUDE.md +1 -0
- package/.agents/skills/update/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/AGENTS.md +45 -0
- package/.agents/skills-archived/anthropic-plan/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/anthropic-plan/AGENTS.md +1 -1
- package/.agents/skills-archived/anthropic-plan/scripts/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/anthropic-plan/scripts/anthropic_plan_scripts_constants/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/anthropic-plan/templates/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/anthropic-plan/test_skill_contract.py +4 -4
- package/.agents/skills-archived/anthropic-plan/workflow/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/auditing-claude-config/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/bugteam/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/bugteam/reference/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/bugteam/reference/obstacles/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/bugteam/scripts/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_code_rules_gate.py +11 -1
- package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_fix_hookspath.py +11 -1
- package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_preflight.py +11 -1
- package/.agents/skills-archived/bugteam/scripts/bugteam_scripts_constants/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/bugteam/scripts/reflow_skill_md.py +3 -3
- package/.agents/skills-archived/codex-review/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/codex-review/reference/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/codex-review/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/codex-review/scripts/codex_usage_probe.py +11 -1
- package/{skills → .agents/skills-archived}/codex-review/scripts/run_codex_review.py +11 -1
- package/{skills → .agents/skills-archived}/codex-review/test_skill_scaffold.py +4 -4
- package/{skills → .agents/skills-archived}/copilot-finding-triage/SKILL.md +1 -1
- package/.agents/skills-archived/copilot-review/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/pr-converge/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/pr-converge/SKILL.md +6 -6
- package/.agents/skills-archived/pr-converge/pr_converge_skill_constants/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/pr-converge/pr_converge_skill_constants/AGENTS.md +1 -1
- package/{skills → .agents/skills-archived}/pr-converge/pr_converge_skill_constants/constants.py +1 -1
- package/.agents/skills-archived/pr-converge/reference/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/pr-converge/reference/multi-pr-orchestration.md +1 -1
- package/.agents/skills-archived/pr-converge/reference/obstacles/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/pr-converge/reference/per-tick.md +3 -3
- package/.agents/skills-archived/pr-converge/scripts/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/pr-converge/scripts/_pr_converge_path_setup.py +17 -2
- package/.agents/skills-archived/pr-converge/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/pr-converge/scripts/reflow_skill_md.py +2 -2
- package/{skills → .agents/skills-archived}/pr-converge/scripts/test__pr_converge_path_setup.py +7 -4
- package/{skills → .agents/skills-archived}/pr-converge/test_portable_pacer_gate.py +6 -2
- package/.agents/skills-archived/pr-converge/workflows/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/pr-converge/workflows/schedule-wakeup-loop.md +1 -1
- package/.agents/skills-archived/recall/.claude/CLAUDE.md +1 -0
- package/.agents/skills-archived/remember/.claude/CLAUDE.md +1 -0
- package/{skills → .agents/skills-archived}/split-pr/reference/proposal-format.md +1 -1
- package/.claude/CLAUDE.md +1 -0
- package/AGENTS.md +34 -58
- package/_shared/AGENTS.md +2 -0
- package/_shared/advisor/reference/sol-rung.md +2 -2
- package/_shared/advisor/reference/third-party-bind.md +1 -1
- package/_shared/advisor/scripts/tests/test_codex_sol_advisor.py +1 -1
- package/_shared/pr-loop/audit-reply-template.md +4 -0
- package/_shared/pr-loop/code-rules-gate.md +1 -1
- package/_shared/pr-loop/fix-protocol.md +7 -6
- package/_shared/pr-loop/gh-payloads.md +8 -6
- package/_shared/pr-loop/precatch-rubric.md +6 -5
- package/_shared/pr-loop/scripts/AGENTS.md +15 -0
- package/_shared/pr-loop/scripts/_pr_converge_path_setup.py +38 -0
- package/_shared/pr-loop/scripts/check_bugbot_ci.py +279 -0
- package/_shared/pr-loop/scripts/check_convergence.py +923 -0
- package/_shared/pr-loop/scripts/check_convergence_availability.py +275 -0
- package/_shared/pr-loop/scripts/check_convergence_gates.py +279 -0
- package/_shared/pr-loop/scripts/check_convergence_thread_gates.py +219 -0
- package/_shared/pr-loop/scripts/check_pending_reviews.py +154 -0
- package/_shared/pr-loop/scripts/codex_down_classifier.py +98 -0
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +1 -0
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/__init__.py +1 -0
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/classifier_constants.py +35 -0
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +82 -0
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/findings_constants.py +18 -0
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/run_constants.py +53 -0
- package/_shared/pr-loop/scripts/codex_usage_probe.py +570 -0
- package/_shared/pr-loop/scripts/conftest.py +43 -0
- package/_shared/pr-loop/scripts/fetch_copilot_reviews.py +134 -0
- package/_shared/pr-loop/scripts/fixtures/auth_failure_synthetic.txt +1 -0
- package/_shared/pr-loop/scripts/fixtures/config_load_failure_v0.125.0.txt +1 -0
- package/_shared/pr-loop/scripts/fixtures/freeform_findings_v0.144.3.txt +6 -0
- package/_shared/pr-loop/scripts/fixtures/model_rejection_v0.125.0.jsonl +5 -0
- package/_shared/pr-loop/scripts/fixtures/structured_findings.txt +13 -0
- package/_shared/pr-loop/scripts/fixtures/success_stream_v0.144.3.jsonl +6 -0
- package/_shared/pr-loop/scripts/fixtures/unknown_failure_synthetic.txt +1 -0
- package/_shared/pr-loop/scripts/fixtures/usage_limit_synthetic.txt +1 -0
- package/_shared/pr-loop/scripts/parse_codex_findings.py +207 -0
- package/_shared/pr-loop/scripts/post_fix_reply.py +168 -0
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +1 -0
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/__init__.py +0 -0
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +70 -0
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/pr_converge_constants.py +118 -0
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +13 -0
- package/_shared/pr-loop/scripts/pr_converge_skill_constants/.claude/CLAUDE.md +1 -0
- package/_shared/pr-loop/scripts/pr_converge_skill_constants/AGENTS.md +26 -0
- package/_shared/pr-loop/scripts/pr_converge_skill_constants/__init__.py +0 -0
- package/_shared/pr-loop/scripts/pr_converge_skill_constants/constants.py +69 -0
- package/_shared/pr-loop/scripts/run_codex_review.py +609 -0
- package/_shared/pr-loop/scripts/test__pr_converge_path_setup.py +30 -0
- package/_shared/pr-loop/scripts/test_check_bugbot_ci.py +312 -0
- package/_shared/pr-loop/scripts/test_check_convergence.py +438 -0
- package/_shared/pr-loop/scripts/test_check_convergence_availability.py +391 -0
- package/_shared/pr-loop/scripts/test_check_convergence_codex.py +517 -0
- package/_shared/pr-loop/scripts/test_check_convergence_contract.py +400 -0
- package/_shared/pr-loop/scripts/test_check_convergence_fixture.py +179 -0
- package/_shared/pr-loop/scripts/test_check_convergence_gates.py +84 -0
- package/_shared/pr-loop/scripts/test_check_convergence_thread_gates.py +99 -0
- package/_shared/pr-loop/scripts/test_codex_down_classifier.py +143 -0
- package/_shared/pr-loop/scripts/test_codex_usage_probe.py +683 -0
- package/_shared/pr-loop/scripts/test_parse_codex_findings.py +130 -0
- package/_shared/pr-loop/scripts/test_run_codex_review.py +969 -0
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +1 -1
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +1 -1
- package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +1 -1
- package/_shared/pr-loop/state-schema.md +20 -28
- package/_shared/process-tree/AGENTS.md +3 -3
- package/bin/AGENTS.md +17 -12
- package/bin/ever-shipped-skills.mjs +34 -3
- package/bin/install-constants.mjs +46 -12
- package/bin/install-plan.mjs +6 -1
- package/bin/install.agents-home.test.mjs +199 -0
- package/bin/install.cursor-rules.test.mjs +3 -3
- package/bin/install.mjs +153 -23
- package/bin/install.plan.test.mjs +1 -0
- package/bin/install.profile-root.test.mjs +54 -1
- package/bin/install.prune.test.mjs +23 -204
- package/bin/install.test.mjs +17 -5
- package/bin/publish-directory-pointer.mjs +175 -0
- package/bin/publish-directory-pointer.test.mjs +129 -0
- package/bin/resolve-install-root.mjs +80 -4
- package/bin/resolve-package-managed-directory.mjs +29 -0
- package/bin/resolve-package-managed-directory.test.mjs +97 -0
- package/commands/AGENTS.md +2 -0
- package/commands/sr-loop.md +3 -0
- package/docs/references/prose-style-enforcement.md +3 -7
- package/hooks/AGENTS.md +0 -3
- package/hooks/blocking/AGENTS.md +0 -2
- package/hooks/blocking/ask_user_question_shape_blocker.py +83 -0
- package/hooks/blocking/hedging_language_blocker.py +1 -0
- package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +10 -6
- package/hooks/blocking/pre_tool_use_dispatcher.py +2 -19
- package/hooks/blocking/state_description_blocker.py +1 -1
- package/hooks/blocking/test_ask_user_question_shape.py +69 -0
- package/hooks/blocking/test_code_rules_command_dispatch.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_magic_slice_bounds.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_split_annotations_length.py +1 -1
- package/hooks/blocking/test_code_rules_js_conventions.py +1 -1
- package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +1 -1
- package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +1 -1
- package/hooks/blocking/test_code_rules_js_sibling_return_object_key_drift.py +1 -1
- package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +1 -1
- package/hooks/blocking/test_fable_spawn_gate.py +1 -1
- package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +1 -1
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +17 -58
- package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +9 -104
- package/hooks/blocking/test_state_description_blocker.py +1 -0
- package/hooks/blocking/test_stop_dispatcher.py +1 -26
- package/hooks/hooks.json +1 -1
- package/hooks/hooks_constants/AGENTS.md +0 -3
- package/hooks/hooks_constants/ask_user_question_shape.py +1 -1
- package/hooks/hooks_constants/ask_user_question_shape_constants.py +73 -0
- package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +1 -2
- package/hooks/hooks_constants/code_rules_path_utils_constants.py +0 -1
- package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +9 -0
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +0 -7
- package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/test_ask_user_question_shape.py +1 -1
- package/hooks/hooks_constants/test_prose_metrics_parity.py +29 -107
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/working_style_prompt_constants.py +9 -10
- package/hooks/session/AGENTS.md +4 -1
- package/hooks/session/test_working_style_prompt.py +8 -4
- package/hooks/session/working_style_prompt.py +4 -2
- package/installable-surfaces.manifest.json +2 -3
- package/package.json +4 -8
- package/rules/AGENTS.md +2 -5
- package/rules/asd-ste100-language.md +39 -0
- package/rules/ask-user-question-required.md +1 -1
- package/rules/long-horizon-autonomy.md +1 -1
- package/scripts/AGENTS.md +1 -0
- package/scripts/Show-Asset.ps1 +106 -0
- package/scripts/active_capability_references.py +38 -8
- package/scripts/claude_chain_usage.py +2 -0
- package/scripts/codex_compat_watcher.py +1 -1
- package/scripts/dev_env_scripts_constants/active_capability_constants.py +5 -2
- package/scripts/dev_env_scripts_constants/claude_chain_usage_constants.py +4 -1
- package/scripts/test_validate_instruction_pairs.py +30 -3
- package/scripts/test_verify_installable_package.py +2 -1
- package/scripts/tests/test_codex_compat_watcher.py +5 -5
- package/scripts/tests/test_engine.py +4 -4
- package/scripts/tests/test_rules.py +5 -5
- package/system-prompts/AGENTS.md +8 -0
- package/system-prompts/software-engineer.xml +8 -3
- package/CLAUDE.md +0 -1
- package/_shared/pr-loop/scripts/README.md +0 -21
- package/agents/CLAUDE.md +0 -1
- package/docs/imagegen.md +0 -22
- package/hooks/blocking/eli11_reply_enforcer.py +0 -436
- package/hooks/blocking/plain_language_blocker.py +0 -758
- package/hooks/blocking/test_eli11_reply_enforcer.py +0 -390
- package/hooks/blocking/test_plain_language_blocker.py +0 -683
- package/hooks/blocking/test_plain_language_blocker_allowlist.py +0 -228
- package/hooks/diagnostic/AGENTS.md +0 -75
- package/hooks/diagnostic/CLAUDE.md +0 -1
- package/hooks/diagnostic/hook_log_extractor.py +0 -875
- package/hooks/diagnostic/hook_log_init.py +0 -202
- package/hooks/diagnostic/hook_log_stop_wrapper.py +0 -26
- package/hooks/diagnostic/migrations/2026-04-25-drop-themes-hook-events.sql +0 -3
- package/hooks/diagnostic/migrations/AGENTS.md +0 -16
- package/hooks/diagnostic/migrations/CLAUDE.md +0 -1
- package/hooks/diagnostic/migrations/README.md +0 -76
- package/hooks/diagnostic/queries/AGENTS.md +0 -19
- package/hooks/diagnostic/queries/CLAUDE.md +0 -1
- package/hooks/diagnostic/queries/block_details_for_hook.sql +0 -26
- package/hooks/diagnostic/queries/blocks_by_category.sql +0 -10
- package/hooks/diagnostic/queries/blocks_by_tool.sql +0 -9
- package/hooks/diagnostic/queries/blocks_last_7_days.sql +0 -11
- package/hooks/diagnostic/queries/top_blockers_last_24_hours.sql +0 -12
- package/hooks/diagnostic/queries/top_blockers_overall.sql +0 -12
- package/hooks/diagnostic/requirements-hook-logs-dev.txt +0 -2
- package/hooks/diagnostic/requirements-hook-logs.txt +0 -1
- package/hooks/diagnostic/schema.sql +0 -51
- package/hooks/diagnostic/test_hook_log_extractor.py +0 -1518
- package/hooks/diagnostic/test_hook_log_init.py +0 -227
- package/hooks/diagnostic/test_hook_log_stop_wrapper.py +0 -17
- package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +0 -94
- package/hooks/hooks_constants/hook_log_extractor_constants.py +0 -233
- package/hooks/hooks_constants/plain_language_blocker_constants.py +0 -366
- package/hooks/hooks_constants/test_hook_log_extractor_constants.py +0 -123
- package/rules/doc-prose-cuts.md +0 -58
- package/rules/eli11-replies.md +0 -36
- package/rules/opus5-communication-contract.md +0 -45
- package/rules/plain-language.md +0 -9
- package/skills/AGENTS.md +0 -72
- package/skills/CLAUDE.md +0 -1
- package/skills/_shared/CLAUDE.md +0 -1
- package/skills/_shared/advisor/CLAUDE.md +0 -1
- package/skills/_shared/pr-loop/CLAUDE.md +0 -1
- package/skills/_shared/pr-loop/prompts/AGENTS.md +0 -9
- package/skills/_shared/pr-loop/prompts/CLAUDE.md +0 -1
- package/skills/_shared/pr-loop/scripts/CLAUDE.md +0 -1
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +0 -1
- package/skills/anthropic-plan/CLAUDE.md +0 -1
- package/skills/anthropic-plan/scripts/CLAUDE.md +0 -1
- package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/CLAUDE.md +0 -1
- package/skills/anthropic-plan/templates/CLAUDE.md +0 -1
- package/skills/anthropic-plan/workflow/CLAUDE.md +0 -1
- package/skills/auditing-claude-config/CLAUDE.md +0 -1
- package/skills/autoconverge/CLAUDE.md +0 -1
- package/skills/autoconverge/reference/CLAUDE.md +0 -1
- package/skills/autoconverge/workflow/CLAUDE.md +0 -1
- package/skills/autoconverge/workflow/autoconverge_report_constants/CLAUDE.md +0 -1
- package/skills/bugteam/CLAUDE.md +0 -1
- package/skills/bugteam/reference/CLAUDE.md +0 -1
- package/skills/bugteam/reference/obstacles/CLAUDE.md +0 -1
- package/skills/bugteam/scripts/CLAUDE.md +0 -1
- package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
- package/skills/codex-review/CLAUDE.md +0 -1
- package/skills/codex-review/reference/CLAUDE.md +0 -1
- package/skills/codex-review/scripts/codex_review_scripts_constants/CLAUDE.md +0 -1
- package/skills/copilot-review/CLAUDE.md +0 -1
- package/skills/everything-search/CLAUDE.md +0 -1
- package/skills/fresh-branch/CLAUDE.md +0 -1
- package/skills/grok-spawn/CLAUDE.md +0 -1
- package/skills/grokify/evals/README.md +0 -72
- package/skills/grokify/evals/parse-payload.test.mjs +0 -171
- package/skills/grokify/evals/run-capability-evals.mjs +0 -545
- package/skills/pr-converge/CLAUDE.md +0 -1
- package/skills/pr-converge/pr_converge_skill_constants/CLAUDE.md +0 -1
- package/skills/pr-converge/reference/CLAUDE.md +0 -1
- package/skills/pr-converge/reference/obstacles/CLAUDE.md +0 -1
- package/skills/pr-converge/scripts/CLAUDE.md +0 -1
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +0 -1
- package/skills/pr-converge/workflows/CLAUDE.md +0 -1
- package/skills/rebase/CLAUDE.md +0 -1
- package/skills/recall/CLAUDE.md +0 -1
- package/skills/remember/CLAUDE.md +0 -1
- package/skills/session-log/CLAUDE.md +0 -1
- package/skills/session-tidy/CLAUDE.md +0 -1
- package/skills/skill-builder/CLAUDE.md +0 -1
- package/skills/skill-builder/references/CLAUDE.md +0 -1
- package/skills/skill-builder/templates/CLAUDE.md +0 -1
- package/skills/skill-builder/workflows/CLAUDE.md +0 -1
- package/skills/task-build/CLAUDE.md +0 -1
- package/skills/update/CLAUDE.md +0 -1
- /package/{agents → .agents/agents}/clean-coder.md +0 -0
- /package/{agents → .agents/agents}/code-quality-agent.md +0 -0
- /package/{agents → .agents/agents}/git-commit-crafter.md +0 -0
- /package/{agents → .agents/agents}/issue-tracker.md +0 -0
- /package/{agents → .agents/agents}/plan-packet-validator.md +0 -0
- /package/{agents → .agents/agents}/pr-description-writer.md +0 -0
- /package/{agents → .agents/agents}/session-advisor.md +0 -0
- /package/{agents → .agents/agents}/skill-writer-agent.md +0 -0
- /package/{skills → .agents/skills}/_shared/advisor/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/_shared/advisor/advisor-protocol.md +0 -0
- /package/{skills → .agents/skills}/_shared/advisor/scripts/README.md +0 -0
- /package/{skills → .agents/skills}/_shared/end-of-run-gotcha-recommendations.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/audit-contract.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/audit-reply-template.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/code-rules-gate.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/fix-protocol.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/gh-payloads.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/post-audit-thread-contract.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/precatch-rubric.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/_cli_utils.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/_path_resolver.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/_xml_utils.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/audit_category_schema.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/build_audit_prompt.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/build_converge_task_list.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/build_fix_prompt.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/init_loop_state.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/preflight_worktree.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/select_converge_pacer.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -0
- /package/{skills/pr-converge/pr_converge_skill_constants → .agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants}/__init__.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/teardown_worktrees.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test__path_resolver.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_init_loop_state.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_write_handoff.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/scripts/write_handoff.py +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/state-schema.md +0 -0
- /package/{skills → .agents/skills}/_shared/pr-loop/worker-spawn.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/SKILL.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/reference/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/reference/closing-report.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/reference/copilot-findings.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/reference/headless-safety.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/reference/multi-pr.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/reference/self-closing-loop.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/test_portable_pacer_gate.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/aggregate_runs.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -0
- /package/{skills/pr-converge/scripts/pr_converge_scripts_constants → .agents/skills/autoconverge/workflow/autoconverge_report_constants}/__init__.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.clean-audit.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.fix-progress.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.p2-advance.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.path-aware.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.precatch.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge.run-input.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge_multi.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/convergence_summary.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/render_report.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/test_aggregate_runs.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/test_convergence_summary.py +0 -0
- /package/{skills → .agents/skills}/autoconverge/workflow/test_render_report.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/SKILL.md +0 -0
- /package/{skills → .agents/skills}/e-code-review/reference/fix.md +0 -0
- /package/{skills → .agents/skills}/e-code-review/reference/loop.md +0 -0
- /package/{skills → .agents/skills}/e-code-review/reference/low.md +0 -0
- /package/{skills → .agents/skills}/e-code-review/reference/medium.md +0 -0
- /package/{skills → .agents/skills}/e-code-review/reference/runner-selection.md +0 -0
- /package/{skills → .agents/skills}/e-code-review/reference/xhigh.md +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/config/e_code_review_effort_constants/__init__.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/config/e_code_review_effort_constants/effort_constants.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/e_code_review_scripts_constants/__init__.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/e_code_review_scripts_constants/finding_pipeline_constants.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/e_code_review_scripts_constants/grok_code_review_constants.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/effort_defaults_evidence.json +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/effort_evaluation.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/finding_pipeline.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/fixtures/demanding.json +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/fixtures/easy.json +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/fixtures/medium.json +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/grok_code_review.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/test_effort_evaluation.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/test_finding_pipeline.py +0 -0
- /package/{skills → .agents/skills}/e-code-review/scripts/test_grok_code_review.py +0 -0
- /package/{skills → .agents/skills}/e-simplify/SKILL.md +0 -0
- /package/{skills → .agents/skills}/everything-search/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/everything-search/SKILL.md +0 -0
- /package/{skills → .agents/skills}/fresh-branch/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/fresh-branch/SKILL.md +0 -0
- /package/{skills → .agents/skills}/fresh-branch/scripts/create_fresh_branch.py +0 -0
- /package/{skills → .agents/skills}/fresh-branch/scripts/fresh_branch_git_commands.py +0 -0
- /package/{skills → .agents/skills}/fresh-branch/scripts/fresh_branch_scripts_constants/__init__.py +0 -0
- /package/{skills → .agents/skills}/fresh-branch/scripts/fresh_branch_scripts_constants/fresh_branch_cli_constants.py +0 -0
- /package/{skills → .agents/skills}/fresh-branch/scripts/pytest.ini +0 -0
- /package/{skills → .agents/skills}/fresh-branch/scripts/test_fresh_branch_git_commands.py +0 -0
- /package/{skills → .agents/skills}/grok-spawn/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/grok-spawn/SKILL.md +0 -0
- /package/{skills → .agents/skills}/grok-spawn/reference/flag-profiles.md +0 -0
- /package/{skills → .agents/skills}/grok-spawn/reference/worker-briefs.md +0 -0
- /package/{skills → .agents/skills}/issue-tracker/SKILL.md +0 -0
- /package/{skills → .agents/skills}/issue-tracker/reference/epic-and-sub-issue-model.md +0 -0
- /package/{skills → .agents/skills}/issue-tracker/reference/handoff-schema.md +0 -0
- /package/{skills → .agents/skills}/issue-tracker/reference/operation-matrix.md +0 -0
- /package/{skills → .agents/skills}/orchestrator/SKILL.md +0 -0
- /package/{skills → .agents/skills}/orchestrator/scripts/status_gate.py +0 -0
- /package/{skills → .agents/skills}/orchestrator/scripts/status_gate_constants/__init__.py +0 -0
- /package/{skills → .agents/skills}/orchestrator/scripts/status_gate_constants/config/__init__.py +0 -0
- /package/{skills → .agents/skills}/orchestrator/scripts/status_gate_constants/config/constants.py +0 -0
- /package/{skills → .agents/skills}/orchestrator/scripts/test_status_gate.py +0 -0
- /package/{skills → .agents/skills}/orchestrator-refresh/SKILL.md +0 -0
- /package/{skills → .agents/skills}/privacy-hygiene/SKILL.md +0 -0
- /package/{skills → .agents/skills}/privacy-hygiene/reference/sweep-procedure.md +0 -0
- /package/{skills → .agents/skills}/prototype/SKILL.md +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/build_sandbox_settings.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/conftest.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/launch_sandbox.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/probe_sandbox_safety.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/__init__.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -0
- /package/{skills → .agents/skills}/prototype/scripts/test_launch_sandbox.py +0 -0
- /package/{skills → .agents/skills}/prototype/workflows/sandbox.md +0 -0
- /package/{skills → .agents/skills}/rebase/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/rebase/SKILL.md +0 -0
- /package/{skills → .agents/skills}/session-log/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/session-log/templates/frontmatter.md +0 -0
- /package/{skills → .agents/skills}/session-tidy/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/session-tidy/SKILL.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/SKILL.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/delegation-map.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/description-field.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/progressive-disclosure.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/self-audit-checklist.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/skill-modularity.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/skill-types.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/references/thariq-x-post-skills.json +0 -0
- /package/{skills → .agents/skills}/skill-builder/templates/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/templates/gap-analysis.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/workflows/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/workflows/improve-skill.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/workflows/new-skill.md +0 -0
- /package/{skills → .agents/skills}/skill-builder/workflows/polish-skill.md +0 -0
- /package/{skills → .agents/skills}/small-cl/SKILL.md +0 -0
- /package/{skills → .agents/skills}/task-build/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/task-build/SKILL.md +0 -0
- /package/{skills → .agents/skills}/task-build/reference/tool-routing.md +0 -0
- /package/{skills → .agents/skills}/team-advisor/SKILL.md +0 -0
- /package/{skills → .agents/skills}/team-advisor/reference/advisor-docs-review.md +0 -0
- /package/{skills → .agents/skills}/update/AGENTS.md +0 -0
- /package/{skills → .agents/skills}/update/SKILL.md +0 -0
- /package/{skills → .agents/skills}/usage-pause/SKILL.md +0 -0
- /package/{skills → .agents/skills}/usage-pause/scripts/resolve_usage_window.py +0 -0
- /package/{skills → .agents/skills}/usage-pause/scripts/test_resolve_usage_window.py +0 -0
- /package/{skills → .agents/skills}/usage-pause/scripts/usage_pause_constants/__init__.py +0 -0
- /package/{skills → .agents/skills}/usage-pause/scripts/usage_pause_constants/resolve_usage_window_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +0 -0
- /package/{skills/_shared/pr-loop/scripts/skills_pr_loop_constants → .agents/skills-archived/anthropic-plan/scripts/anthropic_plan_scripts_constants}/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/validate_packet_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/test_validate_packet.py +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/validate_packet.py +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/templates/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/templates/README.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/templates/build-prompt.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/templates/reuse-audit.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/templates/source-map.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/templates/visual-plan.template.html +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/workflow/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/workflow/plan-packet.contract.test.mjs +0 -0
- /package/{skills → .agents/skills-archived}/anthropic-plan/workflow/plan-packet.mjs +0 -0
- /package/{skills → .agents/skills-archived}/auditing-claude-config/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/auditing-claude-config/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/auditing-claude-config/reference/probe-hook.md +0 -0
- /package/{skills → .agents/skills-archived}/beat-sheet/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/beat-sheet/reference/visual-beats.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/CONSTRAINTS.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/EXAMPLES.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/PROMPTS.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/README.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/audit-and-teammates.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/copilot-gap-analysis.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/design-rationale.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/github-pr-reviews.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-assign-ids.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-capture-excerpts.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-walk-categories.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-write-xml.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-append-summary.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-apply-fixes.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-git-add-commit.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-git-push.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-post-reply.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-publish-summary.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-py-compile.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-read-files.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-resolve-thread.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-test-suite.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-violation-count.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-write-xml.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/reference/team-setup.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/README.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +0 -0
- /package/{skills/anthropic-plan/scripts/anthropic_plan_scripts_constants → .agents/skills-archived/bugteam/scripts/bugteam_scripts_constants}/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/probe_code_rules_enforcer_check_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/reflow_skill_md_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/windows_safe_rmtree_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/probe_code_rules_enforcer_check.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/test_bugteam_code_rules_gate.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/test_bugteam_preflight.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/test_probe_code_rules_enforcer_check.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/test_windows_safe_rmtree.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/scripts/windows_safe_rmtree.py +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/sources.md +0 -0
- /package/{skills → .agents/skills-archived}/bugteam/test_skill_additions.py +0 -0
- /package/{skills → .agents/skills-archived}/closeout/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/closeout/reference/handoff-prompt-template.md +0 -0
- /package/{skills → .agents/skills-archived}/closeout/reference/pii-redaction-checklist.md +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/reference/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/reference/cli-contract.md +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/reference/loop-integration.md +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_down_classifier.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/classifier_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/findings_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/run_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/auth_failure_synthetic.txt +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/config_load_failure_v0.125.0.txt +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/freeform_findings_v0.144.3.txt +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/model_rejection_v0.125.0.jsonl +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/structured_findings.txt +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/success_stream_v0.144.3.jsonl +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/unknown_failure_synthetic.txt +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/usage_limit_synthetic.txt +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/parse_codex_findings.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/test_codex_down_classifier.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/test_codex_usage_probe.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/test_parse_codex_findings.py +0 -0
- /package/{skills → .agents/skills-archived}/codex-review/scripts/test_run_codex_review.py +0 -0
- /package/{skills → .agents/skills-archived}/comments/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/condensing-instructions/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/copilot-finding-triage/reference/tier-rubric.md +0 -0
- /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/conftest.py +0 -0
- /package/{skills/autoconverge/workflow/autoconverge_report_constants → .agents/skills-archived/copilot-finding-triage/scripts/copilot_finding_triage_constants}/__init__.py +0 -0
- /package/{skills/bugteam/scripts/bugteam_scripts_constants → .agents/skills-archived/copilot-finding-triage/scripts/copilot_finding_triage_constants/config}/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/notify_ntfy_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/notify_ntfy.py +0 -0
- /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/test_notify_ntfy.py +0 -0
- /package/{skills → .agents/skills-archived}/copilot-finding-triage/templates/notification.md +0 -0
- /package/{skills → .agents/skills-archived}/copilot-review/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/copilot-review/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/copilot-review/templates/subagent-prompt.md +0 -0
- /package/{skills → .agents/skills-archived}/descriptions/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/emergencies/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/grokify/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/grokify/capability-claims.test.mjs +0 -0
- /package/{skills → .agents/skills-archived}/grokify/templates/handoff-template.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/final-validation-tasks.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/model-routing.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/packet-contract.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/packet-schema.json +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/process-inventory.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/review-loop.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/run-record.schema.json +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/self-audit-tasks.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/task-seeds.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/reference/task-ticket.md +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/config/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/config/constants.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/create_packet.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/load_skill_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_create_packet.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_validate_packet.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_validate_protocol.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_validate_run.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/validate_packet.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/validate_protocol.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/validate_run.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/test_skill_contract.py +0 -0
- /package/{skills → .agents/skills-archived}/plan-to-pr/test_task_ticket_contract.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/AGENTS.md +0 -0
- /package/{skills/copilot-finding-triage/scripts/copilot_finding_triage_constants → .agents/skills-archived/pr-converge/pr_converge_skill_constants}/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/convergence-gates.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/examples.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/fix-protocol.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/ground-rules.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-post-replies.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-publish-summary.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-push.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-read-filelines.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-reset-state.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-resolve-threads.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-stage-commit.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-trigger-bugbot.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-write-test.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/progress-checklist.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/state-schema.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/reference/stop-conditions.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/README.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/caller-window-pid.ps1 +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_bugbot_ci.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence_availability.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence_gates.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence_thread_gates.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_pending_reviews.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/conftest.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue-caller.cmd +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue-stop-others.ps1 +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue.ahk +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue.cmd +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/fetch_copilot_reviews.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/post_fix_reply.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +0 -0
- /package/{skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/config → .agents/skills-archived/pr-converge/scripts/pr_converge_scripts_constants}/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/pr_converge_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_bugbot_ci.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_availability.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_codex.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_contract.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_fixture.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_gates.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_thread_gates.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_cursor_agents_continue.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_reflow_skill_md.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/test_step5_host_branch.py +0 -0
- /package/{skills → .agents/skills-archived}/pr-converge/workflows/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-fix-protocol/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-loop-cloud-transport/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-loop-cloud-transport/reference/identity-and-hooks.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-loop-cloud-transport/reference/substitution-matrix.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-loop-lifecycle/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/pr-loop-lifecycle/reference/teardown-publish-permissions.md +0 -0
- /package/{skills → .agents/skills-archived}/recall/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/recall/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/release-notes-html/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/remember/AGENTS.md +0 -0
- /package/{skills → .agents/skills-archived}/remember/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/reviewer-gates/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/reviews/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/show/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/accessibility.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/art.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/charts.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/core-design.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/erds.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/flowcharts.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/host-and-html.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/illustrative-diagrams.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/interaction.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/mockups.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/quality-gates.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/structural-diagrams.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/subject-inventory.md +0 -0
- /package/{skills → .agents/skills-archived}/show/references/svg-contract.md +0 -0
- /package/{skills → .agents/skills-archived}/show/routing.yaml +0 -0
- /package/{skills → .agents/skills-archived}/show/samples/pr1262-v2.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/scripts/README.md +0 -0
- /package/{skills → .agents/skills-archived}/show/scripts/validate-artifact.py +0 -0
- /package/{skills → .agents/skills-archived}/show/scripts/validate-package.py +0 -0
- /package/{skills → .agents/skills-archived}/show/templates/html-widget.html +0 -0
- /package/{skills → .agents/skills-archived}/show/templates/svg-base.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/css-var.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/dead-ref.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/filled-glyph.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/inherited-fill.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/invalid.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/large-canvas.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/unfilled-connector.svg +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/fixtures/valid.html +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/test_validate-artifact.py +0 -0
- /package/{skills → .agents/skills-archived}/show/tests/test_validators.py +0 -0
- /package/{skills → .agents/skills-archived}/show/workflows/create-visual.md +0 -0
- /package/{skills → .agents/skills-archived}/show/workflows/review-visual.md +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/SKILL.md +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/reference/path-layers.md +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/reference/split-further-loop.md +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/reference/splitting-principles.md +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/analyze_pr.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/categorize_files.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/config/__init__.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/config/dependency_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/config/git_operations_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/config/packing_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/config/plan_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/config/split_pr_constants.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/execute_split_slices.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/pack_files_into_slices.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_dependency_graph.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_git_operations.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_layer_order.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_paginate.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_process_runner.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_script_types.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_title.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_analyze_pr.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_categorize_files.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_categorize_files_packing.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_execute_split_slices.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_dependency_graph.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_git_operations.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_layer_order.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_paginate.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_script_types.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_title.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_dependency_graph.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_plan.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_plan_contract.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_plan_path_normalization.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/verify_dependency_graph.py +0 -0
- /package/{skills → .agents/skills-archived}/split-pr/scripts/verify_plan.py +0 -0
|
@@ -0,0 +1,923 @@
|
|
|
1
|
+
"""Verify every convergence pre-condition for a PR before marking it ready.
|
|
2
|
+
|
|
3
|
+
::
|
|
4
|
+
|
|
5
|
+
check_convergence.py --owner O --repo R --pr-number N [flags]
|
|
6
|
+
exit 0 ok: every gate passed — safe to mark ready
|
|
7
|
+
exit 1 flag: a gate failed (FAIL lines print to stdout)
|
|
8
|
+
exit 2 flag: gh CLI error
|
|
9
|
+
|
|
10
|
+
check_convergence.py --owner O --repo R --pr-number N --fixture PATH [flags]
|
|
11
|
+
Same stdout and exit codes as the live path, reading a frozen GitHub
|
|
12
|
+
API snapshot from PATH instead of calling ``gh`` against current state.
|
|
13
|
+
|
|
14
|
+
Each bypass flag closes one reviewer gate when that reviewer is unavailable.
|
|
15
|
+
``--bugbot-down`` skips the bugbot check-run gate. ``--copilot-down`` skips
|
|
16
|
+
the Copilot review and pending-review gates. ``--bugteam-post-blocked`` skips
|
|
17
|
+
the bugteam CLEAN-review gate. ``--codex-down`` skips the Codex review gate.
|
|
18
|
+
|
|
19
|
+
Bugbot, bugteam, and codex are off by default. Each gate runs only when
|
|
20
|
+
``CLAUDE_REVIEWS_ENABLED`` lists its token, and a token in
|
|
21
|
+
``CLAUDE_REVIEWS_DISABLED`` forces one off even when the opt-in lists it.
|
|
22
|
+
Copilot runs by default and stops only when the disabled list names it. For
|
|
23
|
+
Codex, sticky job-dir state ``codex_down: true`` is a further bypass source
|
|
24
|
+
when the original run could not re-pass ``--codex-down``.
|
|
25
|
+
|
|
26
|
+
Every reviewer waiver is disk-authoritative.
|
|
27
|
+
When ``~/.claude/settings.json`` is readable, its env block is the single source.
|
|
28
|
+
The frozen process env is only a fallback when that disk read fails (logged once).
|
|
29
|
+
A probe error does not waive the gate; the live GitHub checks still run.
|
|
30
|
+
|
|
31
|
+
The Codex gate is conditional-required: it demands
|
|
32
|
+
``codex_clean_at == current_head`` only when the weekly usage probe reports
|
|
33
|
+
more than the probe's threshold percent left. At or below that threshold, null
|
|
34
|
+
usage, the codex token, or ``codex_down`` never blocks ready.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
import argparse
|
|
40
|
+
import json
|
|
41
|
+
import os
|
|
42
|
+
import subprocess
|
|
43
|
+
import sys
|
|
44
|
+
from collections.abc import Callable
|
|
45
|
+
from pathlib import Path
|
|
46
|
+
from typing import NamedTuple
|
|
47
|
+
|
|
48
|
+
import _pr_converge_path_setup # noqa: F401
|
|
49
|
+
from check_convergence_gates import (
|
|
50
|
+
_check_bot_review,
|
|
51
|
+
_check_bugbot,
|
|
52
|
+
_check_bugbot_not_dirty,
|
|
53
|
+
_flatten_paginated_reviews,
|
|
54
|
+
_get_mergeable,
|
|
55
|
+
_get_pr_head_sha,
|
|
56
|
+
_gh_api_paginated,
|
|
57
|
+
_short_sha,
|
|
58
|
+
_sort_reviews_newest_first,
|
|
59
|
+
_evaluate_mergeable_from_pr_object,
|
|
60
|
+
)
|
|
61
|
+
from check_convergence_thread_gates import (
|
|
62
|
+
_check_no_pending_reviews,
|
|
63
|
+
_count_unresolved_bot_threads,
|
|
64
|
+
)
|
|
65
|
+
from codex_review_scripts_constants.codex_usage_probe_constants import (
|
|
66
|
+
USAGE_REPORT_KEY_PERCENT_LEFT,
|
|
67
|
+
)
|
|
68
|
+
from codex_usage_probe import is_codex_review_required, probe_weekly_usage_via_subprocess
|
|
69
|
+
from pr_converge_scripts_constants.convergence_gate_constants import (
|
|
70
|
+
BUGBOT_DOWN_BYPASS_NOTE,
|
|
71
|
+
CLAUDE_JOB_DIR_ENV_VAR_NAME,
|
|
72
|
+
CODEX_BYPASS_DETAIL,
|
|
73
|
+
CODEX_CLEAN_AT_STATE_KEY,
|
|
74
|
+
CODEX_CLEAN_DETAIL_TEMPLATE,
|
|
75
|
+
CODEX_DOWN_STATE_KEY,
|
|
76
|
+
CODEX_GATE_LABEL,
|
|
77
|
+
CODEX_MISSING_CLEAN_DETAIL_TEMPLATE,
|
|
78
|
+
CODEX_SKIPPED_USAGE_DETAIL,
|
|
79
|
+
COPILOT_DOWN_BYPASS_NOTE,
|
|
80
|
+
FIXTURE_DEFAULT_PENDING_DETAIL,
|
|
81
|
+
FIXTURE_DEFAULT_THREADS_DETAIL,
|
|
82
|
+
FIXTURE_KEY_CODEX_CLEAN_AT,
|
|
83
|
+
FIXTURE_KEY_CODEX_PERCENT_LEFT,
|
|
84
|
+
FIXTURE_KEY_HEAD_SHA,
|
|
85
|
+
FIXTURE_KEY_PENDING_REVIEWS_DETAIL,
|
|
86
|
+
FIXTURE_KEY_PENDING_REVIEWS_PASSED,
|
|
87
|
+
FIXTURE_KEY_PR_OBJECT,
|
|
88
|
+
FIXTURE_KEY_REVIEWS,
|
|
89
|
+
FIXTURE_KEY_UNRESOLVED_BOT_THREADS_DETAIL,
|
|
90
|
+
FIXTURE_KEY_UNRESOLVED_BOT_THREADS_PASSED,
|
|
91
|
+
MINIMUM_ABBREVIATED_SHA_LENGTH,
|
|
92
|
+
PR_CONVERGE_STATE_FILENAME,
|
|
93
|
+
)
|
|
94
|
+
from pr_converge_skill_constants.constants import (
|
|
95
|
+
ALL_COPILOT_CLEAN_REVIEW_STATES,
|
|
96
|
+
ALL_COPILOT_DIRTY_REVIEW_STATES,
|
|
97
|
+
BUGTEAM_LEGACY_CLEAN_TOKEN,
|
|
98
|
+
BUGTEAM_LEGACY_HEADER_PREFIX,
|
|
99
|
+
BUGTEAM_NEW_CLEAN_LABEL,
|
|
100
|
+
BUGTEAM_NEW_HEADER_PREFIX,
|
|
101
|
+
COPILOT_LOGIN_FILTER_SUBSTRING,
|
|
102
|
+
GH_REVIEWS_PATH_TEMPLATE,
|
|
103
|
+
REVIEWS_PER_PAGE,
|
|
104
|
+
)
|
|
105
|
+
from reviews_disabled import (
|
|
106
|
+
is_bugbot_disabled_via_env,
|
|
107
|
+
is_copilot_disabled_via_env,
|
|
108
|
+
)
|
|
109
|
+
from check_convergence_availability import (
|
|
110
|
+
_is_bugteam_disabled_via_resolved_settings,
|
|
111
|
+
_is_codex_disabled_via_resolved_settings,
|
|
112
|
+
_resolve_bugbot_waiver,
|
|
113
|
+
_resolve_copilot_waiver,
|
|
114
|
+
_waiver_from_cli_flag,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
JsonObject = dict[str, object]
|
|
118
|
+
GateCondition = tuple[str, tuple[bool, str]]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class ConvergenceFixture(NamedTuple):
|
|
122
|
+
"""Frozen GitHub API snapshot one fixture gate run evaluates."""
|
|
123
|
+
|
|
124
|
+
head_sha: str
|
|
125
|
+
pr_object: JsonObject
|
|
126
|
+
reviews: list[JsonObject]
|
|
127
|
+
is_zero_unresolved_bot_threads: bool
|
|
128
|
+
unresolved_bot_threads_detail: str
|
|
129
|
+
is_no_pending_reviews: bool
|
|
130
|
+
pending_reviews_detail: str
|
|
131
|
+
codex_percent_left: float | None
|
|
132
|
+
codex_clean_at: str | None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class GateContext(NamedTuple):
|
|
136
|
+
"""The PR coordinates and per-reviewer bypass flags one gate run evaluates."""
|
|
137
|
+
|
|
138
|
+
owner: str
|
|
139
|
+
repo: str
|
|
140
|
+
number: int
|
|
141
|
+
head_sha: str
|
|
142
|
+
is_bugbot_down: bool
|
|
143
|
+
is_copilot_down: bool
|
|
144
|
+
is_bugteam_post_blocked: bool
|
|
145
|
+
is_codex_down: bool
|
|
146
|
+
bugbot_bypass_note: str = BUGBOT_DOWN_BYPASS_NOTE
|
|
147
|
+
copilot_bypass_note: str = COPILOT_DOWN_BYPASS_NOTE
|
|
148
|
+
live_codex_clean_at: str | None = None
|
|
149
|
+
fixture: ConvergenceFixture | None = None
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _is_bugteam_review(review_body: str) -> bool:
|
|
153
|
+
"""Return True when a review body opens with a bugteam audit header prefix."""
|
|
154
|
+
return review_body.startswith(BUGTEAM_NEW_HEADER_PREFIX) or review_body.startswith(
|
|
155
|
+
BUGTEAM_LEGACY_HEADER_PREFIX
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _is_clean_bugteam_review(review_body: str) -> bool:
|
|
160
|
+
"""Return True when a bugteam audit review body declares a clean pass."""
|
|
161
|
+
if review_body.startswith(BUGTEAM_NEW_HEADER_PREFIX):
|
|
162
|
+
first_line = review_body.splitlines()[0]
|
|
163
|
+
return BUGTEAM_NEW_CLEAN_LABEL in first_line
|
|
164
|
+
if review_body.startswith(BUGTEAM_LEGACY_HEADER_PREFIX):
|
|
165
|
+
return review_body.rstrip().endswith(BUGTEAM_LEGACY_CLEAN_TOKEN)
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _bugteam_review_detail(review: JsonObject, head_sha: str) -> tuple[bool, str] | None:
|
|
170
|
+
"""Return the pass flag and detail for a bugteam review on HEAD, or None."""
|
|
171
|
+
body = review.get("body", "")
|
|
172
|
+
if not isinstance(body, str) or not _is_bugteam_review(body):
|
|
173
|
+
return None
|
|
174
|
+
commit_id = review.get("commit_id", "")
|
|
175
|
+
if not isinstance(commit_id, str) or not commit_id.startswith(head_sha):
|
|
176
|
+
return None
|
|
177
|
+
review_id = review.get("id", "?")
|
|
178
|
+
short_commit = _short_sha(commit_id)
|
|
179
|
+
if _is_clean_bugteam_review(body):
|
|
180
|
+
return True, f"review {review_id}, clean bugteam audit, commit {short_commit}"
|
|
181
|
+
return False, f"review {review_id}, dirty bugteam audit, commit {short_commit}"
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _evaluate_bugteam_clean_from_reviews(
|
|
185
|
+
all_reviews: list[JsonObject], head_sha: str
|
|
186
|
+
) -> tuple[bool, str]:
|
|
187
|
+
"""Return whether the newest bugteam audit on HEAD is clean (pure, no network).
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
all_reviews: Review objects newest-first as returned by the GitHub reviews API.
|
|
191
|
+
head_sha: Current PR HEAD commit SHA.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
(passed, detail) for the first bugteam review on HEAD, or a missing-review failure.
|
|
195
|
+
"""
|
|
196
|
+
for each_review in all_reviews:
|
|
197
|
+
detail = _bugteam_review_detail(each_review, head_sha)
|
|
198
|
+
if detail is not None:
|
|
199
|
+
return detail
|
|
200
|
+
return False, f"no bugteam review found on {_short_sha(head_sha)}"
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _check_bugteam_clean(*, owner: str, repo: str, number: int, head_sha: str) -> tuple[bool, str]:
|
|
204
|
+
"""Return whether the newest bugteam audit review on HEAD declares a clean pass."""
|
|
205
|
+
endpoint = GH_REVIEWS_PATH_TEMPLATE.format(owner=owner, repo=repo, number=number)
|
|
206
|
+
returncode, stdout = _gh_api_paginated(f"{endpoint}?per_page={REVIEWS_PER_PAGE}")
|
|
207
|
+
if returncode != 0:
|
|
208
|
+
return False, f"gh api error: {stdout}"
|
|
209
|
+
all_flat = _flatten_paginated_reviews(stdout)
|
|
210
|
+
if all_flat is None:
|
|
211
|
+
return False, "unexpected gh api response shape (expected list)"
|
|
212
|
+
return _evaluate_bugteam_clean_from_reviews(all_flat, head_sha)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _bypassed_note(bypass_note: str) -> str:
|
|
216
|
+
"""Format the PASS detail line for a gate bypassed for the given reason."""
|
|
217
|
+
return f"bypassed ({bypass_note})"
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _bugbot_conditions(context: GateContext) -> list[GateCondition]:
|
|
221
|
+
"""Build the Bugbot gate conditions, bypassed when Bugbot is down."""
|
|
222
|
+
if context.is_bugbot_down:
|
|
223
|
+
return [
|
|
224
|
+
(
|
|
225
|
+
"bugbot_clean_at == current_head",
|
|
226
|
+
(True, _bypassed_note(context.bugbot_bypass_note)),
|
|
227
|
+
)
|
|
228
|
+
]
|
|
229
|
+
if context.fixture is not None:
|
|
230
|
+
return [
|
|
231
|
+
(
|
|
232
|
+
"bugbot_clean_at == current_head",
|
|
233
|
+
(False, "fixture has no bugbot check-runs; pass --bugbot-down"),
|
|
234
|
+
)
|
|
235
|
+
]
|
|
236
|
+
conditions: list[GateCondition] = [
|
|
237
|
+
(
|
|
238
|
+
"bugbot_clean_at == current_head",
|
|
239
|
+
_check_bugbot(owner=context.owner, repo=context.repo, sha=context.head_sha),
|
|
240
|
+
)
|
|
241
|
+
]
|
|
242
|
+
if conditions[-1][1][0]:
|
|
243
|
+
conditions.append(
|
|
244
|
+
(
|
|
245
|
+
"bugbot review body clean",
|
|
246
|
+
_check_bugbot_not_dirty(
|
|
247
|
+
owner=context.owner,
|
|
248
|
+
repo=context.repo,
|
|
249
|
+
number=context.number,
|
|
250
|
+
head_sha=context.head_sha,
|
|
251
|
+
),
|
|
252
|
+
)
|
|
253
|
+
)
|
|
254
|
+
return conditions
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _bugteam_condition(context: GateContext) -> GateCondition:
|
|
258
|
+
"""Build the bugteam CLEAN-review condition, skipped when the post was blocked."""
|
|
259
|
+
if context.is_bugteam_post_blocked:
|
|
260
|
+
return ("bugteam_clean_at == current_head", (True, "bypassed (bugteam_post_blocked)"))
|
|
261
|
+
if context.fixture is not None:
|
|
262
|
+
return (
|
|
263
|
+
"bugteam_clean_at == current_head",
|
|
264
|
+
_evaluate_bugteam_clean_from_reviews(context.fixture.reviews, context.head_sha),
|
|
265
|
+
)
|
|
266
|
+
return (
|
|
267
|
+
"bugteam_clean_at == current_head",
|
|
268
|
+
_check_bugteam_clean(
|
|
269
|
+
owner=context.owner,
|
|
270
|
+
repo=context.repo,
|
|
271
|
+
number=context.number,
|
|
272
|
+
head_sha=context.head_sha,
|
|
273
|
+
),
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _copilot_review_condition(context: GateContext) -> GateCondition:
|
|
278
|
+
"""Build the Copilot review gate condition, bypassed when Copilot is down."""
|
|
279
|
+
if context.is_copilot_down:
|
|
280
|
+
return (
|
|
281
|
+
"copilot_clean_at == current_head",
|
|
282
|
+
(True, _bypassed_note(context.copilot_bypass_note)),
|
|
283
|
+
)
|
|
284
|
+
if context.fixture is not None:
|
|
285
|
+
return (
|
|
286
|
+
"copilot_clean_at == current_head",
|
|
287
|
+
(False, "fixture has no copilot review; pass --copilot-down"),
|
|
288
|
+
)
|
|
289
|
+
return (
|
|
290
|
+
"copilot_clean_at == current_head",
|
|
291
|
+
_check_bot_review(
|
|
292
|
+
owner=context.owner,
|
|
293
|
+
repo=context.repo,
|
|
294
|
+
number=context.number,
|
|
295
|
+
head_sha=context.head_sha,
|
|
296
|
+
login_substring=COPILOT_LOGIN_FILTER_SUBSTRING,
|
|
297
|
+
clean_states=ALL_COPILOT_CLEAN_REVIEW_STATES,
|
|
298
|
+
dirty_states=ALL_COPILOT_DIRTY_REVIEW_STATES,
|
|
299
|
+
label="copilot",
|
|
300
|
+
),
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _sha_matches_head(stamp_sha: str, head_sha: str) -> bool:
|
|
305
|
+
"""Return True when a clean-at stamp matches the PR HEAD SHA (full or prefix).
|
|
306
|
+
|
|
307
|
+
::
|
|
308
|
+
|
|
309
|
+
stamp 86454e3d..., head 86454e3d... -> True (full match)
|
|
310
|
+
stamp 86454e3, head 86454e3d... -> True (abbreviated stamp)
|
|
311
|
+
stamp 8, head 86454e3d... -> False (below the abbreviation floor)
|
|
312
|
+
|
|
313
|
+
A prefix shorter than an abbreviated SHA matches many commits, so a stamp
|
|
314
|
+
that short never passes the gate.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
stamp_sha: The ``codex_clean_at`` stamp under test.
|
|
318
|
+
head_sha: Current PR HEAD commit SHA.
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
True when the two name the same commit.
|
|
322
|
+
"""
|
|
323
|
+
if len(stamp_sha) < MINIMUM_ABBREVIATED_SHA_LENGTH:
|
|
324
|
+
return False
|
|
325
|
+
if len(head_sha) < MINIMUM_ABBREVIATED_SHA_LENGTH:
|
|
326
|
+
return False
|
|
327
|
+
lowered_stamp_sha = stamp_sha.lower()
|
|
328
|
+
lowered_head_sha = head_sha.lower()
|
|
329
|
+
return lowered_head_sha.startswith(lowered_stamp_sha) or lowered_stamp_sha.startswith(
|
|
330
|
+
lowered_head_sha
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _evaluate_codex_clean(
|
|
335
|
+
*,
|
|
336
|
+
read_percent_left: Callable[[], float | None],
|
|
337
|
+
codex_clean_at: str | None,
|
|
338
|
+
head_sha: str,
|
|
339
|
+
) -> tuple[bool, str]:
|
|
340
|
+
"""Return whether the conditional Codex gate passes for the given stamp and usage.
|
|
341
|
+
|
|
342
|
+
::
|
|
343
|
+
|
|
344
|
+
clean stamp on head -> pass (usage never read)
|
|
345
|
+
no stamp, percent None or <= limit -> skip (never blocks)
|
|
346
|
+
no stamp, percent > limit -> fail
|
|
347
|
+
|
|
348
|
+
A stamp on the current HEAD settles the gate on its own, so the usage read
|
|
349
|
+
stays behind it: the weekly probe spawns a Codex subprocess, and the common
|
|
350
|
+
already-clean tick has no reason to pay for one.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
read_percent_left: Reads weekly Codex percent remaining, or None when unknown.
|
|
354
|
+
codex_clean_at: HEAD SHA where Codex last reported clean, or None.
|
|
355
|
+
head_sha: Current PR HEAD commit SHA.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
(passed, detail) for the Codex gate condition line.
|
|
359
|
+
"""
|
|
360
|
+
if codex_clean_at is not None and _sha_matches_head(codex_clean_at, head_sha):
|
|
361
|
+
return True, CODEX_CLEAN_DETAIL_TEMPLATE % _short_sha(head_sha)
|
|
362
|
+
if not is_codex_review_required(read_percent_left()):
|
|
363
|
+
return True, CODEX_SKIPPED_USAGE_DETAIL
|
|
364
|
+
return False, CODEX_MISSING_CLEAN_DETAIL_TEMPLATE % _short_sha(head_sha)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def _probe_codex_percent_left() -> float | None:
|
|
368
|
+
"""Probe weekly Codex usage and return percent remaining, or None when unknown."""
|
|
369
|
+
try:
|
|
370
|
+
usage_report = probe_weekly_usage_via_subprocess()
|
|
371
|
+
except (
|
|
372
|
+
FileNotFoundError,
|
|
373
|
+
OSError,
|
|
374
|
+
subprocess.TimeoutExpired,
|
|
375
|
+
subprocess.SubprocessError,
|
|
376
|
+
json.JSONDecodeError,
|
|
377
|
+
ValueError,
|
|
378
|
+
TypeError,
|
|
379
|
+
KeyError,
|
|
380
|
+
):
|
|
381
|
+
return None
|
|
382
|
+
raw_percent = usage_report.get(USAGE_REPORT_KEY_PERCENT_LEFT)
|
|
383
|
+
if isinstance(raw_percent, bool):
|
|
384
|
+
return None
|
|
385
|
+
if isinstance(raw_percent, (int, float)):
|
|
386
|
+
return float(raw_percent)
|
|
387
|
+
return None
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def _read_job_state() -> dict[str, object]:
|
|
391
|
+
"""Read the single-PR job-dir state file, or an empty mapping when unreadable.
|
|
392
|
+
|
|
393
|
+
::
|
|
394
|
+
|
|
395
|
+
CLAUDE_JOB_DIR unset -> {}
|
|
396
|
+
state file absent -> {}
|
|
397
|
+
corrupt or non-object -> {}
|
|
398
|
+
{"codex_down": true} -> {"codex_down": True}
|
|
399
|
+
|
|
400
|
+
Args:
|
|
401
|
+
None.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
The parsed state object, or an empty dict when no state is readable.
|
|
405
|
+
"""
|
|
406
|
+
job_directory = os.environ.get(CLAUDE_JOB_DIR_ENV_VAR_NAME)
|
|
407
|
+
if not job_directory:
|
|
408
|
+
return {}
|
|
409
|
+
state_path = Path(job_directory) / PR_CONVERGE_STATE_FILENAME
|
|
410
|
+
if not state_path.is_file():
|
|
411
|
+
return {}
|
|
412
|
+
try:
|
|
413
|
+
payload = json.loads(state_path.read_text(encoding="utf-8"))
|
|
414
|
+
except (OSError, json.JSONDecodeError):
|
|
415
|
+
return {}
|
|
416
|
+
if not isinstance(payload, dict):
|
|
417
|
+
return {}
|
|
418
|
+
return payload
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def _read_codex_clean_at_from_job_state(all_job_state_fields: dict[str, object]) -> str | None:
|
|
422
|
+
"""Read ``codex_clean_at`` from an already-read job-dir state mapping."""
|
|
423
|
+
clean_at = all_job_state_fields.get(CODEX_CLEAN_AT_STATE_KEY)
|
|
424
|
+
if isinstance(clean_at, str) and clean_at:
|
|
425
|
+
return clean_at
|
|
426
|
+
return None
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def _read_codex_down_from_job_state(all_job_state_fields: dict[str, object]) -> bool:
|
|
430
|
+
"""Return True when job-dir state records sticky ``codex_down`` as JSON true.
|
|
431
|
+
|
|
432
|
+
::
|
|
433
|
+
|
|
434
|
+
{"codex_down": true} -> True
|
|
435
|
+
{"codex_down": false} -> False
|
|
436
|
+
missing key / corrupt -> False
|
|
437
|
+
|
|
438
|
+
Only exact boolean true counts; strings, numbers, and missing values do not.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
all_job_state_fields: Parsed job-dir state, empty when none is readable.
|
|
442
|
+
|
|
443
|
+
Returns:
|
|
444
|
+
True when the state records ``codex_down`` as JSON true.
|
|
445
|
+
"""
|
|
446
|
+
return all_job_state_fields.get(CODEX_DOWN_STATE_KEY) is True
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def _resolve_live_codex_clean_at(
|
|
450
|
+
cli_codex_clean_at: str | None, all_job_state_fields: dict[str, object]
|
|
451
|
+
) -> str | None:
|
|
452
|
+
"""Prefer the CLI stamp, then the job-dir state stamp, for the live Codex gate.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
cli_codex_clean_at: Stamp passed through ``--codex-clean-at``, or None.
|
|
456
|
+
all_job_state_fields: Parsed job-dir state, empty when none is readable.
|
|
457
|
+
|
|
458
|
+
Returns:
|
|
459
|
+
The stamp the live Codex gate checks against HEAD, or None.
|
|
460
|
+
"""
|
|
461
|
+
if cli_codex_clean_at:
|
|
462
|
+
return cli_codex_clean_at
|
|
463
|
+
return _read_codex_clean_at_from_job_state(all_job_state_fields)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def _codex_condition(context: GateContext) -> GateCondition:
|
|
467
|
+
"""Build the conditional Codex gate, bypassed when Codex is down."""
|
|
468
|
+
if context.is_codex_down:
|
|
469
|
+
return (CODEX_GATE_LABEL, (True, CODEX_BYPASS_DETAIL))
|
|
470
|
+
if context.fixture is not None:
|
|
471
|
+
fixture_percent_left = context.fixture.codex_percent_left
|
|
472
|
+
return (
|
|
473
|
+
CODEX_GATE_LABEL,
|
|
474
|
+
_evaluate_codex_clean(
|
|
475
|
+
read_percent_left=lambda: fixture_percent_left,
|
|
476
|
+
codex_clean_at=context.fixture.codex_clean_at,
|
|
477
|
+
head_sha=context.head_sha,
|
|
478
|
+
),
|
|
479
|
+
)
|
|
480
|
+
return (
|
|
481
|
+
CODEX_GATE_LABEL,
|
|
482
|
+
_evaluate_codex_clean(
|
|
483
|
+
read_percent_left=_probe_codex_percent_left,
|
|
484
|
+
codex_clean_at=context.live_codex_clean_at,
|
|
485
|
+
head_sha=context.head_sha,
|
|
486
|
+
),
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def _pending_reviews_condition(context: GateContext) -> GateCondition:
|
|
491
|
+
"""Build the pending-requested-reviews condition, bypassed when Copilot is down."""
|
|
492
|
+
if context.is_copilot_down:
|
|
493
|
+
return (
|
|
494
|
+
"no pending requested reviews",
|
|
495
|
+
(True, _bypassed_note(context.copilot_bypass_note)),
|
|
496
|
+
)
|
|
497
|
+
if context.fixture is not None:
|
|
498
|
+
return (
|
|
499
|
+
"no pending requested reviews",
|
|
500
|
+
(
|
|
501
|
+
context.fixture.is_no_pending_reviews,
|
|
502
|
+
context.fixture.pending_reviews_detail,
|
|
503
|
+
),
|
|
504
|
+
)
|
|
505
|
+
return (
|
|
506
|
+
"no pending requested reviews",
|
|
507
|
+
_check_no_pending_reviews(owner=context.owner, repo=context.repo, number=context.number),
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def _mergeable_condition(context: GateContext) -> GateCondition:
|
|
512
|
+
"""Build the mergeable condition from live gh or the frozen fixture PR object."""
|
|
513
|
+
if context.fixture is not None:
|
|
514
|
+
return (
|
|
515
|
+
"PR is mergeable",
|
|
516
|
+
_evaluate_mergeable_from_pr_object(context.fixture.pr_object),
|
|
517
|
+
)
|
|
518
|
+
return (
|
|
519
|
+
"PR is mergeable",
|
|
520
|
+
_get_mergeable(owner=context.owner, repo=context.repo, number=context.number),
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
def _threads_condition(context: GateContext) -> GateCondition:
|
|
525
|
+
"""Build the unresolved-bot-threads condition from live gh or the fixture."""
|
|
526
|
+
if context.fixture is not None:
|
|
527
|
+
return (
|
|
528
|
+
"zero unresolved bot threads",
|
|
529
|
+
(
|
|
530
|
+
context.fixture.is_zero_unresolved_bot_threads,
|
|
531
|
+
context.fixture.unresolved_bot_threads_detail,
|
|
532
|
+
),
|
|
533
|
+
)
|
|
534
|
+
return (
|
|
535
|
+
"zero unresolved bot threads",
|
|
536
|
+
_count_unresolved_bot_threads(
|
|
537
|
+
owner=context.owner, repo=context.repo, number=context.number
|
|
538
|
+
),
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def _state_conditions(context: GateContext) -> list[GateCondition]:
|
|
543
|
+
"""Build the thread, mergeable, and pending-review conditions in gate order."""
|
|
544
|
+
return [
|
|
545
|
+
_threads_condition(context),
|
|
546
|
+
_mergeable_condition(context),
|
|
547
|
+
_pending_reviews_condition(context),
|
|
548
|
+
]
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
def _build_all_conditions(context: GateContext) -> list[GateCondition]:
|
|
552
|
+
"""Build the ordered convergence conditions the checker prints and grades."""
|
|
553
|
+
conditions = list(_bugbot_conditions(context))
|
|
554
|
+
conditions.append(_bugteam_condition(context))
|
|
555
|
+
conditions.append(_copilot_review_condition(context))
|
|
556
|
+
conditions.append(_codex_condition(context))
|
|
557
|
+
conditions.extend(_state_conditions(context))
|
|
558
|
+
return conditions
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def _print_conditions(all_conditions: list[GateCondition]) -> int:
|
|
562
|
+
"""Write one PASS/FAIL line per condition and return the aggregate exit code."""
|
|
563
|
+
is_all_passed = True
|
|
564
|
+
for each_index, (each_label, (each_passed, each_detail)) in enumerate(all_conditions, start=1):
|
|
565
|
+
status = "PASS" if each_passed else "FAIL"
|
|
566
|
+
sys.stdout.write(f"{each_index}. {each_label}: {status} — {each_detail}\n")
|
|
567
|
+
if not each_passed:
|
|
568
|
+
is_all_passed = False
|
|
569
|
+
sys.stdout.write("\n")
|
|
570
|
+
if is_all_passed:
|
|
571
|
+
sys.stdout.write("All pre-conditions met — PR is ready to mark ready.\n")
|
|
572
|
+
else:
|
|
573
|
+
sys.stdout.write("One or more pre-conditions not met — do not mark ready.\n")
|
|
574
|
+
return 0 if is_all_passed else 1
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def _evaluate_convergence(context: GateContext) -> int:
|
|
578
|
+
"""Write the HEAD line then the per-condition PASS/FAIL lines for a gate run."""
|
|
579
|
+
sys.stdout.write(f"HEAD: {_short_sha(context.head_sha)}\n\n")
|
|
580
|
+
return _print_conditions(_build_all_conditions(context))
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
def _load_convergence_fixture(from_path: Path) -> ConvergenceFixture:
|
|
584
|
+
"""Load a frozen GitHub API snapshot from JSON for fixture replay.
|
|
585
|
+
|
|
586
|
+
Args:
|
|
587
|
+
from_path: Path to a JSON fixture file.
|
|
588
|
+
|
|
589
|
+
Returns:
|
|
590
|
+
ConvergenceFixture with head, reviews, mergeable PR object, and thread/pending facts.
|
|
591
|
+
|
|
592
|
+
Raises:
|
|
593
|
+
ValueError: When required keys are missing or mistyped.
|
|
594
|
+
"""
|
|
595
|
+
payload = json.loads(from_path.read_text(encoding="utf-8"))
|
|
596
|
+
if not isinstance(payload, dict):
|
|
597
|
+
raise ValueError("fixture root must be a JSON object")
|
|
598
|
+
head_sha = payload.get(FIXTURE_KEY_HEAD_SHA)
|
|
599
|
+
pr_object = payload.get(FIXTURE_KEY_PR_OBJECT)
|
|
600
|
+
reviews = payload.get(FIXTURE_KEY_REVIEWS)
|
|
601
|
+
if not isinstance(head_sha, str) or not head_sha:
|
|
602
|
+
raise ValueError("fixture head_sha must be a non-empty string")
|
|
603
|
+
if not isinstance(pr_object, dict):
|
|
604
|
+
raise ValueError("fixture pr_object must be an object")
|
|
605
|
+
if not isinstance(reviews, list):
|
|
606
|
+
raise ValueError("fixture reviews must be a list")
|
|
607
|
+
typed_reviews = _sort_reviews_newest_first(
|
|
608
|
+
[each for each in reviews if isinstance(each, dict)]
|
|
609
|
+
)
|
|
610
|
+
is_threads_ok = payload.get(FIXTURE_KEY_UNRESOLVED_BOT_THREADS_PASSED)
|
|
611
|
+
threads_detail = payload.get(
|
|
612
|
+
FIXTURE_KEY_UNRESOLVED_BOT_THREADS_DETAIL, FIXTURE_DEFAULT_THREADS_DETAIL
|
|
613
|
+
)
|
|
614
|
+
is_pending_ok = payload.get(FIXTURE_KEY_PENDING_REVIEWS_PASSED)
|
|
615
|
+
pending_detail = payload.get(
|
|
616
|
+
FIXTURE_KEY_PENDING_REVIEWS_DETAIL, FIXTURE_DEFAULT_PENDING_DETAIL
|
|
617
|
+
)
|
|
618
|
+
if not isinstance(is_threads_ok, bool):
|
|
619
|
+
raise ValueError("fixture unresolved_bot_threads_passed must be a bool")
|
|
620
|
+
if not isinstance(threads_detail, str):
|
|
621
|
+
raise ValueError("fixture unresolved_bot_threads_detail must be a string")
|
|
622
|
+
if not isinstance(is_pending_ok, bool):
|
|
623
|
+
raise ValueError("fixture pending_reviews_passed must be a bool")
|
|
624
|
+
if not isinstance(pending_detail, str):
|
|
625
|
+
raise ValueError("fixture pending_reviews_detail must be a string")
|
|
626
|
+
codex_percent_left = payload.get(FIXTURE_KEY_CODEX_PERCENT_LEFT)
|
|
627
|
+
codex_clean_at = payload.get(FIXTURE_KEY_CODEX_CLEAN_AT)
|
|
628
|
+
if isinstance(codex_percent_left, bool):
|
|
629
|
+
raise ValueError("fixture codex_percent_left must be a number or null")
|
|
630
|
+
if codex_percent_left is not None and not isinstance(codex_percent_left, (int, float)):
|
|
631
|
+
raise ValueError("fixture codex_percent_left must be a number or null")
|
|
632
|
+
if codex_clean_at is not None and not isinstance(codex_clean_at, str):
|
|
633
|
+
raise ValueError("fixture codex_clean_at must be a string or null")
|
|
634
|
+
typed_percent_left: float | None = (
|
|
635
|
+
float(codex_percent_left) if isinstance(codex_percent_left, (int, float)) else None
|
|
636
|
+
)
|
|
637
|
+
typed_codex_clean_at: str | None = codex_clean_at if isinstance(codex_clean_at, str) else None
|
|
638
|
+
return ConvergenceFixture(
|
|
639
|
+
head_sha=head_sha,
|
|
640
|
+
pr_object=pr_object,
|
|
641
|
+
reviews=typed_reviews,
|
|
642
|
+
is_zero_unresolved_bot_threads=is_threads_ok,
|
|
643
|
+
unresolved_bot_threads_detail=threads_detail,
|
|
644
|
+
is_no_pending_reviews=is_pending_ok,
|
|
645
|
+
pending_reviews_detail=pending_detail,
|
|
646
|
+
codex_percent_left=typed_percent_left,
|
|
647
|
+
codex_clean_at=typed_codex_clean_at,
|
|
648
|
+
)
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
def check_all(
|
|
652
|
+
owner: str,
|
|
653
|
+
repo: str,
|
|
654
|
+
number: int,
|
|
655
|
+
is_bugbot_down: bool,
|
|
656
|
+
is_copilot_down: bool,
|
|
657
|
+
is_bugteam_post_blocked: bool,
|
|
658
|
+
is_codex_down: bool,
|
|
659
|
+
live_codex_clean_at: str | None,
|
|
660
|
+
bugbot_bypass_note: str = BUGBOT_DOWN_BYPASS_NOTE,
|
|
661
|
+
copilot_bypass_note: str = COPILOT_DOWN_BYPASS_NOTE,
|
|
662
|
+
) -> int:
|
|
663
|
+
"""Run every convergence gate and print one PASS/FAIL line per condition.
|
|
664
|
+
|
|
665
|
+
Args:
|
|
666
|
+
owner: GitHub repository owner login.
|
|
667
|
+
repo: GitHub repository name.
|
|
668
|
+
number: Pull request number to inspect.
|
|
669
|
+
is_bugbot_down: True bypasses the bugbot check-run and review-body gates.
|
|
670
|
+
is_copilot_down: True bypasses the Copilot review and pending gates.
|
|
671
|
+
is_bugteam_post_blocked: True skips the bugteam CLEAN-review gate.
|
|
672
|
+
is_codex_down: True bypasses the conditional Codex review gate.
|
|
673
|
+
live_codex_clean_at: Optional SHA stamp for the live Codex clean-at check.
|
|
674
|
+
bugbot_bypass_note: Detail note printed when the bugbot gate is bypassed.
|
|
675
|
+
copilot_bypass_note: Detail note printed when the Copilot gates are bypassed.
|
|
676
|
+
|
|
677
|
+
Returns:
|
|
678
|
+
0 when every gate passes, 1 when at least one gate fails.
|
|
679
|
+
"""
|
|
680
|
+
head_sha = _get_pr_head_sha(owner=owner, repo=repo, number=number)
|
|
681
|
+
context = GateContext(
|
|
682
|
+
owner=owner,
|
|
683
|
+
repo=repo,
|
|
684
|
+
number=number,
|
|
685
|
+
head_sha=head_sha,
|
|
686
|
+
is_bugbot_down=is_bugbot_down,
|
|
687
|
+
is_copilot_down=is_copilot_down,
|
|
688
|
+
is_bugteam_post_blocked=is_bugteam_post_blocked,
|
|
689
|
+
is_codex_down=is_codex_down,
|
|
690
|
+
bugbot_bypass_note=bugbot_bypass_note,
|
|
691
|
+
copilot_bypass_note=copilot_bypass_note,
|
|
692
|
+
live_codex_clean_at=live_codex_clean_at,
|
|
693
|
+
fixture=None,
|
|
694
|
+
)
|
|
695
|
+
return _evaluate_convergence(context)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def _check_all_from_fixture(
|
|
699
|
+
owner: str,
|
|
700
|
+
repo: str,
|
|
701
|
+
number: int,
|
|
702
|
+
fixture: ConvergenceFixture,
|
|
703
|
+
is_bugbot_down: bool,
|
|
704
|
+
is_copilot_down: bool,
|
|
705
|
+
is_bugteam_post_blocked: bool,
|
|
706
|
+
is_codex_down: bool,
|
|
707
|
+
bugbot_bypass_note: str = BUGBOT_DOWN_BYPASS_NOTE,
|
|
708
|
+
copilot_bypass_note: str = COPILOT_DOWN_BYPASS_NOTE,
|
|
709
|
+
) -> int:
|
|
710
|
+
"""Run every convergence gate against a frozen API snapshot.
|
|
711
|
+
|
|
712
|
+
Args:
|
|
713
|
+
owner: GitHub repository owner login.
|
|
714
|
+
repo: GitHub repository name.
|
|
715
|
+
number: Pull request number recorded in the snapshot.
|
|
716
|
+
fixture: Frozen GitHub API snapshot (no live `gh` calls).
|
|
717
|
+
is_bugbot_down: True bypasses the bugbot check-run and review-body gates.
|
|
718
|
+
is_copilot_down: True bypasses the Copilot review and pending gates.
|
|
719
|
+
is_bugteam_post_blocked: True skips the bugteam CLEAN-review gate.
|
|
720
|
+
is_codex_down: True bypasses the conditional Codex review gate.
|
|
721
|
+
bugbot_bypass_note: Detail note printed when the bugbot gate is bypassed.
|
|
722
|
+
copilot_bypass_note: Detail note printed when the Copilot gates are bypassed.
|
|
723
|
+
|
|
724
|
+
Returns:
|
|
725
|
+
0 when every gate passes, 1 when at least one gate fails.
|
|
726
|
+
"""
|
|
727
|
+
context = GateContext(
|
|
728
|
+
owner=owner,
|
|
729
|
+
repo=repo,
|
|
730
|
+
number=number,
|
|
731
|
+
head_sha=fixture.head_sha,
|
|
732
|
+
is_bugbot_down=is_bugbot_down,
|
|
733
|
+
is_copilot_down=is_copilot_down,
|
|
734
|
+
is_bugteam_post_blocked=is_bugteam_post_blocked,
|
|
735
|
+
is_codex_down=is_codex_down,
|
|
736
|
+
bugbot_bypass_note=bugbot_bypass_note,
|
|
737
|
+
copilot_bypass_note=copilot_bypass_note,
|
|
738
|
+
live_codex_clean_at=None,
|
|
739
|
+
fixture=fixture,
|
|
740
|
+
)
|
|
741
|
+
return _evaluate_convergence(context)
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
def _build_argument_parser() -> argparse.ArgumentParser:
|
|
745
|
+
"""Build the command-line argument parser for the convergence checker."""
|
|
746
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
747
|
+
parser.add_argument("--owner", required=True, help="GitHub repository owner")
|
|
748
|
+
parser.add_argument("--repo", required=True, help="GitHub repository name")
|
|
749
|
+
parser.add_argument("--pr-number", required=True, type=int, help="Pull request number")
|
|
750
|
+
parser.add_argument(
|
|
751
|
+
"--fixture",
|
|
752
|
+
default=None,
|
|
753
|
+
help="Path to a frozen GitHub API JSON snapshot for offline replay.",
|
|
754
|
+
)
|
|
755
|
+
parser.add_argument(
|
|
756
|
+
"--bugbot-down",
|
|
757
|
+
action="store_true",
|
|
758
|
+
help="Bypass the bugbot check-run gate when Cursor Bugbot is unreachable on HEAD.",
|
|
759
|
+
)
|
|
760
|
+
parser.add_argument(
|
|
761
|
+
"--copilot-down",
|
|
762
|
+
action="store_true",
|
|
763
|
+
help="Bypass the Copilot review and pending-review gates when Copilot is down on HEAD.",
|
|
764
|
+
)
|
|
765
|
+
parser.add_argument(
|
|
766
|
+
"--bugteam-post-blocked",
|
|
767
|
+
action="store_true",
|
|
768
|
+
help="Skip the bugteam CLEAN-review gate when the environment refused the CLEAN post on HEAD.",
|
|
769
|
+
)
|
|
770
|
+
parser.add_argument(
|
|
771
|
+
"--codex-down",
|
|
772
|
+
action="store_true",
|
|
773
|
+
help="Bypass the conditional Codex review gate when Codex is down or opted out.",
|
|
774
|
+
)
|
|
775
|
+
parser.add_argument(
|
|
776
|
+
"--codex-clean-at",
|
|
777
|
+
default=None,
|
|
778
|
+
help="HEAD SHA where Codex last reported clean (live path; optional when job-dir state holds it).",
|
|
779
|
+
)
|
|
780
|
+
return parser
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
def parse_arguments(all_argv: list[str]) -> argparse.Namespace:
|
|
784
|
+
"""Parse command-line arguments for the convergence checker.
|
|
785
|
+
|
|
786
|
+
Args:
|
|
787
|
+
all_argv: Argument list excluding the program name.
|
|
788
|
+
|
|
789
|
+
Returns:
|
|
790
|
+
Namespace exposing owner, repo, pr_number, fixture, bugbot_down, copilot_down,
|
|
791
|
+
bugteam_post_blocked, codex_down, and codex_clean_at attributes.
|
|
792
|
+
"""
|
|
793
|
+
return _build_argument_parser().parse_args(all_argv)
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
def _resolve_bugbot_down(is_bugbot_down_flag: bool) -> bool:
|
|
797
|
+
"""Pinned contract/unit-test helper for the bugbot flag and env bypass.
|
|
798
|
+
|
|
799
|
+
Production ``main()`` resolves Bugbot waivers through ``_resolve_bugbot_waiver``.
|
|
800
|
+
This function serves only pinned contract and unit tests; issue #120 tracks
|
|
801
|
+
its removal.
|
|
802
|
+
"""
|
|
803
|
+
return is_bugbot_down_flag or is_bugbot_disabled_via_env()
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
def _resolve_copilot_down(is_copilot_down_flag: bool) -> bool:
|
|
807
|
+
"""Pinned contract/unit-test helper for the copilot flag and env bypass.
|
|
808
|
+
|
|
809
|
+
Production ``main()`` resolves Copilot waivers through ``_resolve_copilot_waiver``.
|
|
810
|
+
This function serves only pinned contract and unit tests; issue #120 tracks
|
|
811
|
+
its removal.
|
|
812
|
+
"""
|
|
813
|
+
return is_copilot_down_flag or is_copilot_disabled_via_env()
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
def _resolve_bugteam_post_blocked(is_bugteam_post_blocked_flag: bool) -> bool:
|
|
817
|
+
"""Combine the --bugteam-post-blocked flag with the resolved bugteam opt-in.
|
|
818
|
+
|
|
819
|
+
::
|
|
820
|
+
|
|
821
|
+
flag True -> True (caller passed the flag)
|
|
822
|
+
flag False, reviews-enabled lists bugteam -> False (gate runs)
|
|
823
|
+
flag False, neither list names bugteam -> True (off by default)
|
|
824
|
+
flag False, reviews-disabled lists bugteam -> True (opt-out wins)
|
|
825
|
+
|
|
826
|
+
Bugteam is off by default and runs only on an explicit opt-in. Settings on
|
|
827
|
+
disk are the source when readable, so a settings.json opt-in reaches the
|
|
828
|
+
mark-ready blocker hook, which re-runs this script with no flags. The
|
|
829
|
+
process env is the fallback when that disk read fails.
|
|
830
|
+
"""
|
|
831
|
+
return is_bugteam_post_blocked_flag or _is_bugteam_disabled_via_resolved_settings()
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
def _resolve_codex_down(
|
|
835
|
+
is_codex_down_flag: bool, all_job_state_fields: dict[str, object]
|
|
836
|
+
) -> bool:
|
|
837
|
+
"""Combine --codex-down, env opt-out, and sticky job-state ``codex_down``.
|
|
838
|
+
|
|
839
|
+
::
|
|
840
|
+
|
|
841
|
+
flag True, env unset, job unset -> True (caller passed the flag)
|
|
842
|
+
flag False, reviews-disabled lists codex -> True (exported token)
|
|
843
|
+
flag False, env unset, job codex_down true -> True (sticky job-state)
|
|
844
|
+
flag False, env unset, job unset or false -> False (gate may run)
|
|
845
|
+
|
|
846
|
+
The mark-ready blocker hook re-runs this script with no flags, so the env
|
|
847
|
+
token and sticky job-state ``codex_down`` both carry the bypass into that
|
|
848
|
+
re-check when the original run cannot re-pass ``--codex-down``.
|
|
849
|
+
|
|
850
|
+
Args:
|
|
851
|
+
is_codex_down_flag: True when the caller passed ``--codex-down``.
|
|
852
|
+
all_job_state_fields: Parsed job-dir state, empty when none is readable.
|
|
853
|
+
|
|
854
|
+
Returns:
|
|
855
|
+
True when any of the three bypass sources is in force.
|
|
856
|
+
"""
|
|
857
|
+
return (
|
|
858
|
+
is_codex_down_flag
|
|
859
|
+
or _is_codex_disabled_via_resolved_settings()
|
|
860
|
+
or _read_codex_down_from_job_state(all_job_state_fields)
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
def main(
|
|
865
|
+
all_arguments: list[str],
|
|
866
|
+
bugbot_bypass_note: str = BUGBOT_DOWN_BYPASS_NOTE,
|
|
867
|
+
copilot_bypass_note: str = COPILOT_DOWN_BYPASS_NOTE,
|
|
868
|
+
) -> int:
|
|
869
|
+
"""Run the script end-to-end against parsed CLI arguments.
|
|
870
|
+
|
|
871
|
+
Args:
|
|
872
|
+
all_arguments: Argument list excluding the program name.
|
|
873
|
+
bugbot_bypass_note: Note printed when the bugbot gate is bypassed.
|
|
874
|
+
copilot_bypass_note: Note printed when the Copilot gates are bypassed.
|
|
875
|
+
|
|
876
|
+
Returns:
|
|
877
|
+
0 on full convergence, 1 on one or more gate failures.
|
|
878
|
+
"""
|
|
879
|
+
arguments = parse_arguments(all_arguments)
|
|
880
|
+
all_job_state_fields = _read_job_state()
|
|
881
|
+
is_bugteam_post_blocked = _resolve_bugteam_post_blocked(arguments.bugteam_post_blocked)
|
|
882
|
+
is_codex_down = _resolve_codex_down(arguments.codex_down, all_job_state_fields)
|
|
883
|
+
fixture_path = getattr(arguments, "fixture", None)
|
|
884
|
+
if fixture_path:
|
|
885
|
+
bugbot_waiver = _waiver_from_cli_flag(
|
|
886
|
+
arguments.bugbot_down, bugbot_bypass_note
|
|
887
|
+
)
|
|
888
|
+
copilot_waiver = _waiver_from_cli_flag(
|
|
889
|
+
arguments.copilot_down, copilot_bypass_note
|
|
890
|
+
)
|
|
891
|
+
fixture = _load_convergence_fixture(Path(fixture_path))
|
|
892
|
+
return _check_all_from_fixture(
|
|
893
|
+
owner=arguments.owner,
|
|
894
|
+
repo=arguments.repo,
|
|
895
|
+
number=getattr(arguments, "pr_number"),
|
|
896
|
+
fixture=fixture,
|
|
897
|
+
is_bugbot_down=bugbot_waiver.is_waived,
|
|
898
|
+
is_copilot_down=copilot_waiver.is_waived,
|
|
899
|
+
is_bugteam_post_blocked=is_bugteam_post_blocked,
|
|
900
|
+
is_codex_down=is_codex_down,
|
|
901
|
+
bugbot_bypass_note=bugbot_waiver.bypass_note or bugbot_bypass_note,
|
|
902
|
+
copilot_bypass_note=copilot_waiver.bypass_note or copilot_bypass_note,
|
|
903
|
+
)
|
|
904
|
+
bugbot_waiver = _resolve_bugbot_waiver(arguments.bugbot_down)
|
|
905
|
+
copilot_waiver = _resolve_copilot_waiver(arguments.copilot_down)
|
|
906
|
+
return check_all(
|
|
907
|
+
owner=arguments.owner,
|
|
908
|
+
repo=arguments.repo,
|
|
909
|
+
number=getattr(arguments, "pr_number"),
|
|
910
|
+
is_bugbot_down=bugbot_waiver.is_waived,
|
|
911
|
+
is_copilot_down=copilot_waiver.is_waived,
|
|
912
|
+
is_bugteam_post_blocked=is_bugteam_post_blocked,
|
|
913
|
+
is_codex_down=is_codex_down,
|
|
914
|
+
live_codex_clean_at=_resolve_live_codex_clean_at(
|
|
915
|
+
arguments.codex_clean_at, all_job_state_fields
|
|
916
|
+
),
|
|
917
|
+
bugbot_bypass_note=bugbot_waiver.bypass_note or bugbot_bypass_note,
|
|
918
|
+
copilot_bypass_note=copilot_waiver.bypass_note or copilot_bypass_note,
|
|
919
|
+
)
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
if __name__ == "__main__":
|
|
923
|
+
raise SystemExit(main(sys.argv[1:]))
|