claude-dev-env 4.2.0 → 7.0.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/pr-description-writer.md +2 -2
- package/.agents/agents/test_agent_frontmatter.py +2 -2
- package/.agents/agents/test_pr_description_writer_style.py +1 -3
- package/.agents/skills/e-code-review/SKILL.md +12 -12
- package/.agents/skills/e-code-review/preflight-proposal.contract.test.mjs +20 -0
- package/.agents/skills/e-code-review/reference/fix.md +15 -17
- package/.agents/skills/e-code-review/reference/loop.md +35 -39
- package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +2 -1
- package/.agents/skills/e-code-review/reference/preflight-proposal.md +44 -9
- package/.agents/skills/e-code-review/reference/runner-selection.md +13 -14
- package/.agents/skills/issue-tracker/SKILL.md +7 -0
- package/.agents/skills/pull-request/SKILL.md +216 -0
- package/.agents/skills/pull-request/reference/publication-tasks.md +18 -0
- package/.agents/skills/pull-request/scripts/github_pr_command_constants/__init__.py +1 -0
- package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/__init__.py +1 -0
- package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +69 -0
- package/.agents/skills/pull-request/scripts/pull_request.py +265 -0
- package/.agents/skills/pull-request/scripts/recover_legacy_author.py +251 -0
- package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +58 -0
- package/.agents/skills/pull-request/scripts/test_pull_request.py +396 -0
- package/.agents/skills/pull-request/scripts/test_recover_legacy_author.py +221 -0
- package/.agents/skills/skill-builder/SKILL.md +3 -196
- package/.agents/skills/test-runner/SKILL.md +69 -0
- package/.agents/skills/test-runner/scripts/preflight_checks.py +365 -0
- package/.agents/skills/test-runner/scripts/run_tests.py +316 -0
- package/.agents/skills/test-runner/scripts/test_preflight_checks.py +185 -0
- package/.agents/skills/test-runner/scripts/test_run_tests.py +281 -0
- package/.agents/skills/test-runner/scripts/test_runner_constants/__init__.py +1 -0
- package/.agents/skills/test-runner/scripts/test_runner_constants/config/__init__.py +1 -0
- package/.agents/skills/test-runner/scripts/test_runner_constants/config/constants.py +96 -0
- package/.agents/skills-archived/pr-loop-cloud-transport/reference/identity-and-hooks.md +1 -1
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
- package/bin/ever-shipped-skills.mjs +2 -0
- package/bin/ever-shipped-skills.test.mjs +8 -0
- package/bin/install.agents-home.test.mjs +15 -13
- package/bin/install.mjs +37 -1
- package/bin/install.policy-lint.test.mjs +78 -0
- package/bin/install.prune.test.mjs +149 -20
- package/bin/install.pstack-plugin.test.mjs +114 -0
- package/bin/install.test.mjs +61 -7
- package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
- package/hooks/advisory/pr_done_reminder.py +342 -0
- package/hooks/advisory/test_pr_done_reminder.py +249 -0
- package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
- package/hooks/blocking/code_rules_paired_test.py +22 -15
- package/hooks/blocking/pii_prevention_blocker.py +32 -51
- package/hooks/blocking/test_bash_post_call_dispatcher.py +55 -17
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +1 -4
- package/hooks/blocking/test_code_rules_command_dispatch.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
- package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
- package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
- package/hooks/blocking/test_pii_prevention_blocker.py +37 -89
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +68 -133
- package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +18 -18
- package/hooks/gh_post_body_texts.py +195 -0
- package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
- package/hooks/git-hooks/pre_commit.py +52 -11
- package/hooks/git-hooks/test_installed_policy_lint.py +159 -0
- package/hooks/git-hooks/test_native_policy_commit.py +87 -0
- package/hooks/git-hooks/test_pre_commit.py +246 -0
- package/hooks/hooks.json +1 -16
- package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -2
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -8
- package/hooks/hooks_constants/gh_post_body_texts_constants.py +12 -0
- package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -43
- package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +17 -7
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +0 -7
- package/hooks/hooks_constants/test_failure_recorder_constants.py +3 -3
- package/hooks/hooks_constants/test_gh_post_body_texts_constants.py +19 -0
- package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
- package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +20 -32
- package/hooks/observability/test_failure_recorder.py +1 -1
- package/hooks/pyproject.toml +1 -1
- package/hooks/test_gh_post_body_texts.py +79 -0
- package/package.json +2 -2
- package/rules/durable-post-artifacts.md +32 -20
- package/rules/gh-cli-conventions.md +23 -13
- package/rules/git-workflow.md +21 -8
- package/scripts/check.ps1 +0 -1
- package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
- package/scripts/ci/installer-lifecycle.test.mjs +26 -0
- package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
- package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
- package/scripts/durable_post_lint.py +206 -0
- package/scripts/durable_post_lint_config/config/constants.py +96 -0
- package/scripts/durable_post_lint_config/config/test_constants.py +25 -0
- package/scripts/policy_lint/adapter_configuration.py +53 -12
- package/scripts/policy_lint/adapter_detectors.py +13 -6
- package/scripts/policy_lint/adapters.py +7 -4
- package/scripts/policy_lint/config/constants.py +5 -0
- package/scripts/policy_lint/engine.py +48 -4
- package/scripts/policy_lint/model.py +1 -0
- package/scripts/policy_lint/registry.py +1 -1
- package/scripts/policy_lint/selection.py +2 -1
- package/scripts/policy_lint/selection_git.py +2 -0
- package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
- package/scripts/repository_checks/config/constants.py +0 -5
- package/scripts/shared_tree_paths.py +32 -3
- package/scripts/test_durable_post_lint.py +332 -0
- package/scripts/test_shared_tree_paths.py +33 -0
- package/scripts/tests/test_adapter_configuration.py +54 -0
- package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
- package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
- package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
- package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
- package/scripts/tests/test_policy_lint_selection.py +25 -2
- package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
- package/scripts/tests/test_rules.py +3 -7
- package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
- package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
- package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
- package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
- package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
- package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
- package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
- package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
- package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
- package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
- package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
- package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
- package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
- package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
- package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
- package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
- package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
- package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
- package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
- package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
- package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
- package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
- package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
- package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
- package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
- package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
- package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
- package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
- package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
- package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
- package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
- package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
- package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
- package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
- package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
- package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
- package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
- package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
- package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
- package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
- package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/SKILL.md +0 -431
- package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
- package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
- package/.agents/skills/autoconverge/reference/convergence.md +0 -219
- package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
- package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
- package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
- package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
- package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
- package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
- package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
- package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
- package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
- package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
- package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
- package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
- package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
- package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
- package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
- package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
- package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
- package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
- package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
- package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
- package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
- package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
- package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
- package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
- package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
- package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
- package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
- package/.agents/skills/hitl/SKILL.md +0 -45
- package/.agents/skills/pr-cleanup/SKILL.md +0 -140
- package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
- package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
- package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
- package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
- package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
- package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
- package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
- package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
- package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
- package/.agents/skills/pr-refinement/SKILL.md +0 -31
- package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
- package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
- package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
- package/.agents/skills/pr-small-cl/SKILL.md +0 -52
- package/.agents/skills/pr-title-description/SKILL.md +0 -96
- package/.agents/skills/prototype/SKILL.md +0 -85
- package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
- package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
- package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
- package/.agents/skills/prototype/scripts/conftest.py +0 -15
- package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
- package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
- package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
- package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
- package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
- package/.agents/skills/prototype/workflows/promotion.md +0 -25
- package/.agents/skills/prototype/workflows/sandbox.md +0 -35
- package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
- package/.agents/skills/rebase/AGENTS.md +0 -1
- package/.agents/skills/rebase/SKILL.md +0 -178
- package/.agents/skills/review-router/SKILL.md +0 -51
- package/.agents/skills/review-router/reference/route-policy.json +0 -7
- package/.agents/skills/review-router/reference/task-seeds.md +0 -1
- package/.agents/skills/review-router/scripts/conftest.py +0 -4
- package/.agents/skills/review-router/scripts/review_router.py +0 -50
- package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
- package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
- 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 +0 -13
- package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
- package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
- package/.agents/skills/review-tier/SKILL.md +0 -56
- package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
- package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
- package/.agents/skills/review-tier/scripts/conftest.py +0 -4
- package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
- package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
- 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 +0 -29
- package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
- package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
- package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
- package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
- package/.agents/skills/session-log/AGENTS.md +0 -1
- package/.agents/skills/session-log/SKILL.md +0 -170
- package/.agents/skills/session-log/templates/frontmatter.md +0 -40
- package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
- package/.agents/skills/session-tidy/AGENTS.md +0 -1
- package/.agents/skills/session-tidy/SKILL.md +0 -191
- package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
- package/.agents/skills/skill-builder/references/description-field.md +0 -111
- package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
- package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
- package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
- package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
- package/.agents/skills/skill-builder/references/skill-types.md +0 -232
- package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
- package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
- package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
- package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
- package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
- package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
- package/.agents/skills/update/.claude/CLAUDE.md +0 -1
- package/.agents/skills/update/AGENTS.md +0 -1
- package/.agents/skills/update/SKILL.md +0 -190
- package/_shared/pr-loop/AGENTS.md +0 -1
- package/_shared/pr-loop/CLAUDE.md +0 -1
- package/_shared/pr-loop/audit-contract.md +0 -183
- package/_shared/pr-loop/audit-reply-template.md +0 -151
- package/_shared/pr-loop/code-rules-gate.md +0 -65
- package/_shared/pr-loop/fix-protocol.md +0 -60
- package/_shared/pr-loop/gh-payloads.md +0 -75
- package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
- package/_shared/pr-loop/precatch-rubric.md +0 -66
- package/_shared/pr-loop/preflight-proposal.md +0 -56
- package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
- package/_shared/pr-loop/state-schema.md +0 -45
- package/_shared/pr-loop/worker-spawn.md +0 -189
- package/hooks/_gh_pr_author_swap_utils.py +0 -1225
- package/hooks/blocking/conventional_pr_title_gate.py +0 -443
- package/hooks/blocking/gh_body_arg_blocker.py +0 -176
- package/hooks/blocking/gh_pr_author_enforcer.py +0 -487
- package/hooks/blocking/gh_pr_author_restore.py +0 -105
- package/hooks/blocking/pr_description_writer_gate.py +0 -256
- package/hooks/blocking/test_conventional_pr_title_gate.py +0 -640
- package/hooks/blocking/test_gh_body_arg_blocker.py +0 -441
- package/hooks/blocking/test_gh_pr_author_enforcer.py +0 -1166
- package/hooks/blocking/test_gh_pr_author_restore.py +0 -513
- package/hooks/blocking/test_gh_pr_author_swap_utils.py +0 -910
- package/hooks/blocking/test_pr_description_writer_gate.py +0 -234
- package/hooks/blocking/test_preflight_check.py +0 -343
- package/hooks/blocking/test_test_preflight_check.py +0 -80
- package/hooks/blocking/test_volatile_path_in_post_blocker.py +0 -322
- package/hooks/blocking/volatile_path_in_post_blocker.py +0 -461
- package/hooks/hooks_constants/conventional_pr_title_gate_constants.py +0 -58
- package/hooks/hooks_constants/gh_pr_author_swap_constants.py +0 -76
- package/hooks/hooks_constants/pr_description_writer_gate_constants.py +0 -73
- package/hooks/hooks_constants/volatile_path_in_post_blocker_constants.py +0 -55
- package/hooks/observability/pr_description_writer_spawn_tracker.py +0 -113
- package/hooks/observability/test_pr_description_writer_spawn_tracker.py +0 -150
- package/hooks/session/gh_pr_author_session_cleanup.py +0 -175
- package/hooks/session/test_gh_pr_author_session_cleanup.py +0 -576
- package/hooks/test__gh_pr_author_swap_utils.py +0 -333
|
@@ -1,441 +0,0 @@
|
|
|
1
|
-
"""Unit tests for gh-body-arg-blocker PreToolUse hook."""
|
|
2
|
-
|
|
3
|
-
import importlib.util
|
|
4
|
-
import pathlib
|
|
5
|
-
import sys
|
|
6
|
-
|
|
7
|
-
_HOOK_DIR = pathlib.Path(__file__).parent
|
|
8
|
-
if str(_HOOK_DIR) not in sys.path:
|
|
9
|
-
sys.path.insert(0, str(_HOOK_DIR))
|
|
10
|
-
|
|
11
|
-
hook_spec = importlib.util.spec_from_file_location(
|
|
12
|
-
"gh_body_arg_blocker",
|
|
13
|
-
_HOOK_DIR / "gh_body_arg_blocker.py",
|
|
14
|
-
)
|
|
15
|
-
assert hook_spec is not None
|
|
16
|
-
assert hook_spec.loader is not None
|
|
17
|
-
hook_module = importlib.util.module_from_spec(hook_spec)
|
|
18
|
-
hook_spec.loader.exec_module(hook_module)
|
|
19
|
-
_uses_body_string_arg = hook_module._uses_body_string_arg
|
|
20
|
-
_has_backtick = hook_module._has_backtick
|
|
21
|
-
|
|
22
|
-
from blocking._gh_body_arg_utils import (
|
|
23
|
-
_all_equals_prefixes_for_skip,
|
|
24
|
-
_quoted_value_starts_split,
|
|
25
|
-
all_body_flag_prefixes,
|
|
26
|
-
count_extra_tokens_to_skip_for_split_quoted_value,
|
|
27
|
-
iter_significant_tokens,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def test_blocks_issue_create_with_body_string() -> None:
|
|
32
|
-
assert _uses_body_string_arg('gh issue create --title "T" --body "text"')
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def test_blocks_issue_edit_with_body_string() -> None:
|
|
36
|
-
assert _uses_body_string_arg('gh issue edit 42 --body "updated text"')
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def test_blocks_issue_comment_with_body_string() -> None:
|
|
40
|
-
assert _uses_body_string_arg('gh issue comment 42 --body "my comment"')
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def test_blocks_pr_create_with_body_string() -> None:
|
|
44
|
-
assert _uses_body_string_arg('gh pr create --title "T" --body "desc"')
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def test_blocks_pr_edit_with_body_string() -> None:
|
|
48
|
-
assert _uses_body_string_arg('gh pr edit 10 --body "new desc"')
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def test_blocks_pr_comment_with_body_string() -> None:
|
|
52
|
-
assert _uses_body_string_arg('gh pr comment 10 --body "LGTM"')
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def test_blocks_pr_review_with_body_string() -> None:
|
|
56
|
-
assert _uses_body_string_arg('gh pr review 10 --approve --body "looks good"')
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def test_blocks_short_b_flag() -> None:
|
|
60
|
-
assert _uses_body_string_arg('gh pr create --title "T" -b "desc"')
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def test_blocks_pr_create_with_body_equals_syntax() -> None:
|
|
64
|
-
assert _uses_body_string_arg('gh pr create --title "T" --body="text"')
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def test_blocks_pr_create_with_short_b_equals_syntax() -> None:
|
|
68
|
-
assert _uses_body_string_arg('gh pr create --title "T" -b="text"')
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def test_blocks_multiline_bash_continuation_body_on_later_line() -> None:
|
|
72
|
-
command = 'gh pr create \\\n --title "T" \\\n --body "text"\n'
|
|
73
|
-
assert _uses_body_string_arg(command)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def test_blocks_multiline_continuation_with_trailing_whitespace() -> None:
|
|
77
|
-
"""Continuation marker followed by trailing spaces must still join lines."""
|
|
78
|
-
command = 'gh pr create \\ \n --title "T" \\ \n --body "text"\n'
|
|
79
|
-
assert _uses_body_string_arg(command)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def test_blocks_multiline_powershell_continuation_body_on_later_line() -> None:
|
|
83
|
-
"""PowerShell backtick continuation lines must be joined before tokenizing."""
|
|
84
|
-
command = 'gh pr create `\n --title "T" `\n --body "text"\n'
|
|
85
|
-
assert _uses_body_string_arg(command)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def test_blocks_multiline_powershell_continuation_with_trailing_whitespace() -> None:
|
|
89
|
-
"""PowerShell backtick continuation with trailing spaces must still join."""
|
|
90
|
-
command = 'gh pr create ` \n --title "T" ` \n --body "text"\n'
|
|
91
|
-
assert _uses_body_string_arg(command)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def test_approves_body_file() -> None:
|
|
95
|
-
assert not _uses_body_string_arg(
|
|
96
|
-
'gh pr create --title "T" --body-file /tmp/body.md'
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def test_approves_body_file_equals_syntax() -> None:
|
|
101
|
-
assert not _uses_body_string_arg(
|
|
102
|
-
'gh pr create --title "T" --body-file=/tmp/body.md'
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def test_approves_issue_create_with_body_file() -> None:
|
|
107
|
-
assert not _uses_body_string_arg(
|
|
108
|
-
'gh issue create --title "T" --body-file /tmp/body.md'
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def test_approves_unrelated_gh_command() -> None:
|
|
113
|
-
assert not _uses_body_string_arg("gh pr list --repo owner/repo")
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def test_approves_gh_pr_merge() -> None:
|
|
117
|
-
assert not _uses_body_string_arg("gh pr merge 10 --squash")
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def test_approves_empty_command() -> None:
|
|
121
|
-
assert not _uses_body_string_arg("")
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def test_no_false_positive_body_in_title_value() -> None:
|
|
125
|
-
"""--body inside a quoted --title value must not trigger."""
|
|
126
|
-
assert not _uses_body_string_arg(
|
|
127
|
-
'gh pr create --title "block gh --body string arg" --body-file /tmp/b.md'
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def test_no_false_positive_body_as_title_value() -> None:
|
|
132
|
-
"""--title "--body" must not trigger; posix=False retains quotes so the value is not a bare flag."""
|
|
133
|
-
assert not _uses_body_string_arg(
|
|
134
|
-
'gh pr create --title "--body" --body-file /tmp/b.md'
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def test_no_false_positive_windows_path_in_body_file() -> None:
|
|
139
|
-
"""Unquoted Windows path with backslashes in --body-file must be approved without token corruption."""
|
|
140
|
-
assert not _uses_body_string_arg(
|
|
141
|
-
r'gh pr create --title "T" --body-file C:\Users\example\tmp\body.md'
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def test_no_false_positive_heredoc_body_text() -> None:
|
|
146
|
-
"""Multiline command where body content mentions --body must not trigger."""
|
|
147
|
-
command = (
|
|
148
|
-
"gh pr create --title 'My PR' --body-file /tmp/body.md\n"
|
|
149
|
-
"# body content below mentions --body for documentation\n"
|
|
150
|
-
'# Use --body-file not --body "string"\n'
|
|
151
|
-
)
|
|
152
|
-
assert not _uses_body_string_arg(command)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def test_no_false_positive_unparseable_command() -> None:
|
|
156
|
-
"""Unparseable line WITHOUT --body token must approve (out of hook scope)."""
|
|
157
|
-
assert not _uses_body_string_arg("gh pr create --title 'unmatched quote here")
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def test_blocks_unparseable_command_when_body_token_present() -> None:
|
|
161
|
-
"""C2: shlex-unparseable command on affected subcommand WITH --body must BLOCK.
|
|
162
|
-
|
|
163
|
-
A heredoc-style command like `gh pr create --body "$(cat <<EOF...)"` raises
|
|
164
|
-
ValueError in shlex.split(posix=False); silently approving lets the exact
|
|
165
|
-
pattern this hook exists to block slip through. Detect a bare --body literal
|
|
166
|
-
via regex and deny.
|
|
167
|
-
"""
|
|
168
|
-
command = 'gh pr create --title "T" --body "$(cat <<EOF\nbody text\nEOF\n)"'
|
|
169
|
-
assert _uses_body_string_arg(command)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
def test_blocks_unparseable_command_with_short_b_token_present() -> None:
|
|
173
|
-
"""C2 short form: unparseable command (odd single quote) with bare -b must BLOCK."""
|
|
174
|
-
command = "gh pr comment 42 --unterminated 'quote here -b short body text"
|
|
175
|
-
assert _uses_body_string_arg(command)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def test_approves_body_file_dash_stdin_sentinel() -> None:
|
|
179
|
-
"""`gh pr create --body-file -` reads body from stdin and is allowed."""
|
|
180
|
-
assert not _uses_body_string_arg("gh pr create --title 'T' --body-file -")
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def test_blocks_crlf_line_endings_with_bash_continuation() -> None:
|
|
184
|
-
"""CRLF line endings must not break bash continuation joining."""
|
|
185
|
-
command = 'gh pr create \\\r\n --title "T" \\\r\n --body "text"\r\n'
|
|
186
|
-
assert _uses_body_string_arg(command)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
def test_blocks_continuation_with_tab_after_marker() -> None:
|
|
190
|
-
"""Tab whitespace after a continuation marker still counts as continuation."""
|
|
191
|
-
command = 'gh pr create \\\t\n --title "T" \\\t\n --body "text"\n'
|
|
192
|
-
assert _uses_body_string_arg(command)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def test_blocks_utf8_body_with_emoji() -> None:
|
|
196
|
-
"""UTF-8 body content (emoji) must still be detected as a body string."""
|
|
197
|
-
assert _uses_body_string_arg('gh pr create --title "T" --body "ship it 🚀"')
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
def test_blocks_pr_review_request_changes_short_b() -> None:
|
|
201
|
-
"""gh pr review --request-changes -b "text" must block."""
|
|
202
|
-
assert _uses_body_string_arg(
|
|
203
|
-
'gh pr review 10 --request-changes -b "needs work"'
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
def test_blocks_empty_body_string() -> None:
|
|
208
|
-
"""`gh pr create --body=""` is still a body-string call; must block."""
|
|
209
|
-
assert _uses_body_string_arg('gh pr create --title "T" --body=""')
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
def test_blocks_body_file_followed_by_body_string() -> None:
|
|
213
|
-
"""H5: malformed `gh pr create --body-file --body "text"` must BLOCK.
|
|
214
|
-
|
|
215
|
-
Without the flag-shape guard, --body-file consumes --body as its path and
|
|
216
|
-
the real body string slips through as a positional. Treat a value-taking
|
|
217
|
-
flag as value-missing when the next token is itself flag-shaped.
|
|
218
|
-
"""
|
|
219
|
-
assert _uses_body_string_arg(
|
|
220
|
-
'gh pr create --body-file --body "real body text"'
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def test_blocks_windows_path_with_trailing_backslash_continuation() -> None:
|
|
225
|
-
"""C1: prior line ending in `C:\\Users\\example\\` must still continue lines.
|
|
226
|
-
|
|
227
|
-
Naive `count("\\\\") % 2 == 1` mis-classifies this (count=4, even -> no
|
|
228
|
-
continuation) and misses --body on the next line. Counting only the
|
|
229
|
-
trailing run of backslashes correctly identifies a single trailing
|
|
230
|
-
backslash as a continuation marker.
|
|
231
|
-
"""
|
|
232
|
-
command = (
|
|
233
|
-
'gh pr create --title C:\\Users\\example\\ \\\n'
|
|
234
|
-
' --body "real body text"\n'
|
|
235
|
-
)
|
|
236
|
-
assert _uses_body_string_arg(command)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
def test_does_not_join_lines_after_markdown_fence() -> None:
|
|
240
|
-
"""C1: a prior line ending in three backticks (count=3, odd) must NOT continue.
|
|
241
|
-
|
|
242
|
-
Old logic treated any odd backtick count as a PowerShell continuation; a
|
|
243
|
-
closing markdown fence trailing the line would falsely join the next line.
|
|
244
|
-
The fix requires whitespace before a trailing backtick (PowerShell
|
|
245
|
-
continuation marker is `<space>` + backtick + newline) so a bare ``` line
|
|
246
|
-
end does not continue.
|
|
247
|
-
"""
|
|
248
|
-
command = (
|
|
249
|
-
"echo ```\n"
|
|
250
|
-
'gh pr create --title "T" --body "real body text"\n'
|
|
251
|
-
)
|
|
252
|
-
assert _uses_body_string_arg(command) is False
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
def test_does_not_false_positive_equals_form_in_title_value() -> None:
|
|
256
|
-
"""`--title="use --body x"` posix=False keeps the value quoted; must approve."""
|
|
257
|
-
assert not _uses_body_string_arg(
|
|
258
|
-
'gh pr create --title="use --body x" --body-file /tmp/b.md'
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
def test_blocks_short_body_file_F_then_body_string_later() -> None:
|
|
263
|
-
"""`-F /path` (short for --body-file) consumes its value, then --body must still block."""
|
|
264
|
-
assert _uses_body_string_arg(
|
|
265
|
-
'gh pr create -F /tmp/file.md --body "extra body"'
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
def test_approves_short_body_file_F_alone() -> None:
|
|
270
|
-
"""`-F /path` alone must be approved (it is the short form of --body-file)."""
|
|
271
|
-
assert not _uses_body_string_arg(
|
|
272
|
-
'gh pr create --title "T" -F /tmp/file.md'
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def test_approves_template_flag_value_does_not_trigger() -> None:
|
|
277
|
-
"""`--template path` consumes its value; `--body` inside path must not trigger."""
|
|
278
|
-
assert not _uses_body_string_arg(
|
|
279
|
-
'gh pr create --title "T" --template /tmp/--body-template.md --body-file /tmp/b.md'
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
def test_approves_recover_flag_value() -> None:
|
|
284
|
-
"""`--recover path` is value-taking and must not leak `--body` mis-detection."""
|
|
285
|
-
assert not _uses_body_string_arg(
|
|
286
|
-
'gh pr create --recover /tmp/state.json --body-file /tmp/b.md'
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
def test_approves_body_file_only_shlex_unparseable() -> None:
|
|
291
|
-
"""loop1-1: shlex-unparseable command with only --body-file must NOT block.
|
|
292
|
-
|
|
293
|
-
The old \b boundary in _BARE_BODY_TOKEN_PATTERN fired between 'y' and '-'
|
|
294
|
-
in '--body-file', causing any unparseable command containing only --body-file
|
|
295
|
-
(no bare --body) to be incorrectly blocked.
|
|
296
|
-
"""
|
|
297
|
-
assert not _uses_body_string_arg(
|
|
298
|
-
"gh pr create --title 'unmatched --body-file /tmp/body.md"
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
def test_blocks_body_equals_spaced_value() -> None:
|
|
303
|
-
"""loop1-3: --body='has space' split by shlex(posix=False) into two tokens.
|
|
304
|
-
|
|
305
|
-
shlex.split(posix=False) splits `--body='has space'` into ["--body='has", "space'"].
|
|
306
|
-
The continuation token "space'" must be skipped, not yielded as a significant
|
|
307
|
-
positional — the leading --body='has token must still trigger a block.
|
|
308
|
-
"""
|
|
309
|
-
assert _uses_body_string_arg(
|
|
310
|
-
"gh pr create --title 'T' --body='has space'"
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
def test_blocks_short_b_equals_spaced_value() -> None:
|
|
315
|
-
"""loop1-3: -b='has space' split by shlex(posix=False) — continuation token skipped."""
|
|
316
|
-
assert _uses_body_string_arg(
|
|
317
|
-
"gh pr create --title 'T' -b='has space'"
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
def test_blocks_body_after_unclosed_quoted_title() -> None:
|
|
322
|
-
"""loop2-1: unclosed quote in --title= must not consume --body token.
|
|
323
|
-
|
|
324
|
-
shlex.split(posix=False) keeps --title="unclosed as one token whose value
|
|
325
|
-
starts with a quote but has no closing match among subsequent tokens.
|
|
326
|
-
count_extra_tokens_to_skip_for_split_quoted_value must return 0 (not the
|
|
327
|
-
full remaining list length) so the following --body flag stays visible.
|
|
328
|
-
"""
|
|
329
|
-
assert _uses_body_string_arg(
|
|
330
|
-
'gh pr create --title="unclosed --body "real body"'
|
|
331
|
-
)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
def test_space_form_value_flag_remaining_excludes_consumed_value() -> None:
|
|
335
|
-
"""loop2-2: remaining_tokens for space-form value flag must not include the consumed value.
|
|
336
|
-
|
|
337
|
-
When iter_significant_tokens yields (--title, remaining) for --title MyTitle,
|
|
338
|
-
remaining must contain only tokens after MyTitle — not MyTitle itself.
|
|
339
|
-
"""
|
|
340
|
-
all_yielded = list(iter_significant_tokens('gh pr create --title MyTitle --body "desc"'))
|
|
341
|
-
title_remaining = next(remaining for token, remaining in all_yielded if token == "--title")
|
|
342
|
-
assert "MyTitle" not in title_remaining
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
def test_quoted_value_starts_split_unclosed_single_quote() -> None:
|
|
346
|
-
assert _quoted_value_starts_split("'it") is True
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
def test_quoted_value_starts_split_fully_closed() -> None:
|
|
350
|
-
assert _quoted_value_starts_split("'hello'") is False
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
def test_quoted_value_starts_split_double_quote_unclosed() -> None:
|
|
354
|
-
assert _quoted_value_starts_split('"hello') is True
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
def test_count_extra_tokens_returns_none_when_exhausted() -> None:
|
|
358
|
-
result = count_extra_tokens_to_skip_for_split_quoted_value([], "'unclosed")
|
|
359
|
-
assert result is None
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
def test_count_extra_tokens_returns_none_no_closing_in_remaining() -> None:
|
|
363
|
-
result = count_extra_tokens_to_skip_for_split_quoted_value(["word", "another"], "'unclosed")
|
|
364
|
-
assert result is None
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
def test_count_extra_tokens_returns_zero_for_self_contained() -> None:
|
|
368
|
-
result = count_extra_tokens_to_skip_for_split_quoted_value(["next"], "'complete'")
|
|
369
|
-
assert result == 0
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
def test_all_body_flag_prefixes_used_for_equals_skip() -> None:
|
|
373
|
-
for each_prefix in all_body_flag_prefixes:
|
|
374
|
-
assert each_prefix in _all_equals_prefixes_for_skip
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
def test_has_backtick_with_plain_text_body() -> None:
|
|
378
|
-
assert not _has_backtick('gh issue comment 42 --body "bugbot run"')
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
def test_has_backtick_with_markdown_body() -> None:
|
|
382
|
-
assert _has_backtick('gh pr create --title "T" --body "Fixes `foo`"')
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
def test_has_backtick_with_short_b_plain_text() -> None:
|
|
386
|
-
assert not _has_backtick('gh pr comment 10 -b "LGTM"')
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
def test_has_backtick_with_equals_form_plain_text() -> None:
|
|
390
|
-
assert not _has_backtick('gh pr create --title "T" --body="bugbot run"')
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
def test_has_backtick_with_empty_body() -> None:
|
|
394
|
-
assert not _has_backtick('gh pr create --title "T" --body=""')
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
def test_has_backtick_bash_continuation_stripped() -> None:
|
|
398
|
-
"""Bash backslash line continuations are stripped before checking."""
|
|
399
|
-
command = 'gh pr create \\\n --title "T" \\\n --body "bugbot run"\n'
|
|
400
|
-
assert not _has_backtick(command)
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
def test_has_backtick_powershell_continuation_not_stripped_in_bash_context() -> None:
|
|
404
|
-
"""PowerShell backtick continuations are real backticks under the Bash tool.
|
|
405
|
-
|
|
406
|
-
The hook runs on Bash tool invocations where PowerShell-style backtick
|
|
407
|
-
continuations are not continuation markers. Any backtick character in
|
|
408
|
-
the command is a literal backtick that must be detected.
|
|
409
|
-
"""
|
|
410
|
-
command = 'gh pr create `\n --title "T" `\n --body "bugbot run"\n'
|
|
411
|
-
assert _has_backtick(command)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
def test_has_backtick_content_backtick_at_line_end() -> None:
|
|
415
|
-
"""A backtick at end of line in body content must be detected (not mistaken for continuation)."""
|
|
416
|
-
command = 'gh pr create --title "T" --body "Thanks `\n@user"'
|
|
417
|
-
assert _has_backtick(command)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
def test_has_backtick_multi_line_body() -> None:
|
|
421
|
-
"""Backtick on a non-first line of a multi-line body must be detected."""
|
|
422
|
-
command = 'gh pr create --title "T" --body "First line.\nSecond with `code`."'
|
|
423
|
-
assert _has_backtick(command)
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
def test_has_backtick_inside_unclosed_double_quoted_body_value() -> None:
|
|
427
|
-
"""Trailing backtick inside an unclosed --body "..." opening line counts as body content.
|
|
428
|
-
|
|
429
|
-
The first line carries an opening double-quote for --body that is not
|
|
430
|
-
closed on that line (odd quote count = 3). The trailing backtick is body
|
|
431
|
-
content (an inline-code opening), not a PowerShell continuation marker.
|
|
432
|
-
The unclosed-quote check preserves the original line including its
|
|
433
|
-
trailing backtick, so _has_backtick sees the backtick and returns True.
|
|
434
|
-
"""
|
|
435
|
-
command = (
|
|
436
|
-
'gh pr create --title "T" --body "Thanks `\n'
|
|
437
|
-
' this continues the body\n'
|
|
438
|
-
' with more text"\n'
|
|
439
|
-
)
|
|
440
|
-
assert _has_backtick(command)
|
|
441
|
-
|