claude-dev-env 2.12.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
- package/_shared/pr-loop/scripts/test_code_rules_gate.py +0 -26
- package/agents/CLAUDE.md +1 -2
- package/agents/pr-description-writer.md +11 -81
- package/bin/install.mjs +48 -9
- package/bin/install.prune.test.mjs +26 -0
- package/bin/install.settings-defaults.test.mjs +60 -33
- package/bin/install.test.mjs +2 -4
- package/commands/sr-loop.md +9 -5
- package/docs/CLAUDE.md +0 -1
- package/docs/references/CLAUDE.md +0 -1
- package/hooks/CLAUDE.md +1 -1
- package/hooks/blocking/CLAUDE.md +2 -27
- package/hooks/blocking/config/CLAUDE.md +1 -13
- package/hooks/blocking/conventional_pr_title_gate.py +1 -2
- package/hooks/blocking/send_user_file_open_locally_blocker.py +1 -1
- package/hooks/blocking/stop_dispatcher.py +4 -4
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -3
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +6 -7
- package/hooks/blocking/test_send_user_file_open_locally_blocker.py +4 -3
- package/hooks/blocking/test_shared_stdin_adoption.py +0 -2
- package/hooks/diagnostic/CLAUDE.md +3 -3
- package/hooks/diagnostic/hook_log_extractor.py +2 -36
- package/hooks/diagnostic/hook_log_stop_wrapper.py +6 -155
- package/hooks/diagnostic/test_hook_log_extractor.py +8 -21
- package/hooks/diagnostic/test_hook_log_stop_wrapper.py +3 -331
- package/hooks/git-hooks/git_hooks_constants/__init__.py +0 -6
- package/hooks/git-hooks/pre_push.py +3 -85
- package/hooks/git-hooks/test_pre_push.py +0 -130
- package/hooks/hooks.json +0 -35
- package/hooks/hooks_constants/CLAUDE.md +0 -9
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -11
- package/hooks/hooks_constants/convergence_branch_constants.py +0 -1
- package/hooks/hooks_constants/fable_spawn_gate_constants.py +3 -4
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +0 -8
- package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +1 -6
- package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +1 -26
- package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +0 -5
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -1
- package/hooks/lifecycle/CLAUDE.md +1 -3
- package/package.json +1 -1
- package/rules/CLAUDE.md +0 -2
- package/rules/gh-cli-conventions.md +0 -1
- package/rules/git-workflow.md +1 -3
- package/scripts/CLAUDE.md +0 -1
- package/scripts/_code_review_test_support.py +0 -95
- package/scripts/dev_env_scripts_constants/code_review_constants.py +9 -98
- package/scripts/dev_env_scripts_constants/test_code_review_constants.py +1 -44
- package/scripts/invoke_code_review.py +8 -451
- package/scripts/test_invoke_code_review.py +5 -61
- package/scripts/test_invoke_code_review_cli.py +1 -45
- package/scripts/test_invoke_code_review_contract.py +1 -118
- package/settings.json +1 -10
- package/skills/CLAUDE.md +8 -0
- package/skills/autoconverge/reference/CLAUDE.md +1 -1
- package/skills/autoconverge/reference/convergence.md +7 -7
- package/skills/autoconverge/reference/gotchas.md +3 -10
- package/skills/autoconverge/workflow/converge.contract.test.mjs +53 -1388
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +4 -3
- package/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +33 -493
- package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +15 -97
- package/skills/autoconverge/workflow/converge.mjs +201 -238
- package/skills/autoconverge/workflow/converge.precatch.test.mjs +1 -1
- package/skills/bugteam/CONSTRAINTS.md +1 -1
- package/skills/bugteam/SKILL.md +9 -0
- package/skills/bugteam/reference/audit-and-teammates.md +10 -6
- package/skills/bugteam/test_skill_additions.py +9 -0
- package/skills/comments/SKILL.md +65 -0
- package/skills/descriptions/SKILL.md +51 -0
- package/skills/emergencies/SKILL.md +42 -0
- package/skills/imagegen/SKILL.md +21 -0
- package/skills/imagegen/scripts/config/__init__.py +1 -0
- package/skills/imagegen/scripts/config/constants.py +28 -0
- package/skills/imagegen/scripts/imagegen.py +45 -0
- package/skills/imagegen/scripts/imagegen_core.py +528 -0
- package/skills/imagegen/scripts/test_imagegen.py +204 -0
- package/skills/orchestrator/SKILL.md +2 -4
- package/skills/plan-to-pr/SKILL.md +6 -7
- package/skills/plan-to-pr/reference/final-validation-tasks.md +1 -1
- package/skills/plan-to-pr/reference/process-inventory.md +2 -2
- package/skills/plan-to-pr/reference/review-loop.md +2 -2
- package/skills/plan-to-pr/reference/run-record.schema.json +1 -1
- package/skills/plan-to-pr/reference/task-seeds.md +1 -1
- package/skills/plan-to-pr/reference/task-ticket.md +3 -4
- package/skills/plan-to-pr/scripts/config/constants.py +1 -2
- package/skills/plan-to-pr/scripts/test_validate_protocol.py +1 -1
- package/skills/plan-to-pr/test_skill_contract.py +2 -2
- package/skills/pr-converge/SKILL.md +13 -16
- package/skills/pr-converge/reference/progress-checklist.md +6 -5
- package/skills/pr-converge/reference/state-schema.md +1 -27
- package/skills/pr-loop-cloud-transport/SKILL.md +1 -1
- package/skills/pr-loop-cloud-transport/reference/identity-and-hooks.md +3 -3
- package/skills/pr-loop-lifecycle/SKILL.md +1 -1
- package/skills/pr-loop-lifecycle/reference/teardown-publish-permissions.md +1 -1
- package/skills/prototype/SKILL.md +4 -4
- package/skills/prototype/reference/honest-limitations.md +4 -4
- package/skills/prototype/reference/promotion-tasks.md +2 -2
- package/skills/prototype/workflows/promotion.md +4 -6
- package/skills/reviews/SKILL.md +85 -0
- package/skills/small-cl/SKILL.md +52 -0
- package/agents/code-verifier.md +0 -74
- package/docs/PR_DESCRIPTION_GUIDE.md +0 -157
- package/docs/references/code-review-enforcement.md +0 -132
- package/hooks/blocking/code_review_enforcement_config_bootstrap.py +0 -53
- package/hooks/blocking/code_review_gate_deny.py +0 -74
- package/hooks/blocking/code_review_pr_create_gate.py +0 -198
- package/hooks/blocking/code_review_push_gate.py +0 -145
- package/hooks/blocking/code_review_stamp_directory_write_blocker.py +0 -348
- package/hooks/blocking/code_review_stamp_store.py +0 -233
- package/hooks/blocking/code_review_stamp_write_blocker_parts/__init__.py +0 -7
- package/hooks/blocking/code_review_stamp_write_blocker_parts/conftest.py +0 -15
- package/hooks/blocking/code_review_stamp_write_blocker_parts/obfuscated_stamp_path_reference.py +0 -212
- package/hooks/blocking/code_review_stamp_write_blocker_parts/split_directory_change_into_stamp.py +0 -138
- package/hooks/blocking/code_review_stamp_write_blocker_parts/test_obfuscated_stamp_path_reference.py +0 -49
- package/hooks/blocking/code_review_stamp_write_blocker_parts/test_split_directory_change_into_stamp.py +0 -38
- package/hooks/blocking/code_verifier_spawn_preflight_gate.py +0 -483
- package/hooks/blocking/config/code_review_enforcement_constants.py +0 -143
- package/hooks/blocking/config/test_code_review_enforcement_constants.py +0 -166
- package/hooks/blocking/config/verified_commit_constants.py +0 -160
- package/hooks/blocking/config/verified_commit_context_constants.py +0 -21
- package/hooks/blocking/config/verified_commit_gate_output_constants.py +0 -14
- package/hooks/blocking/conftest.py +0 -123
- package/hooks/blocking/convergence_gate_blocker.py +0 -310
- package/hooks/blocking/pr_converge_bugteam_enforcer.py +0 -170
- package/hooks/blocking/pr_description_body_audit.py +0 -148
- package/hooks/blocking/pr_description_command_parser.py +0 -237
- package/hooks/blocking/pr_description_enforcer.py +0 -227
- package/hooks/blocking/pr_description_pr_number.py +0 -155
- package/hooks/blocking/pr_description_proof_of_work.py +0 -385
- package/hooks/blocking/pr_description_readability.py +0 -364
- package/hooks/blocking/reviewer_spawn_gate.py +0 -182
- package/hooks/blocking/test_code_review_enforcement_config_bootstrap.py +0 -62
- package/hooks/blocking/test_code_review_gate_deny.py +0 -54
- package/hooks/blocking/test_code_review_pr_create_gate.py +0 -199
- package/hooks/blocking/test_code_review_push_gate.py +0 -205
- package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +0 -199
- package/hooks/blocking/test_code_review_stamp_store.py +0 -205
- package/hooks/blocking/test_code_verifier_spawn_preflight_gate.py +0 -710
- package/hooks/blocking/test_code_verifier_tools_contract.py +0 -28
- package/hooks/blocking/test_convergence_gate_blocker.py +0 -428
- package/hooks/blocking/test_pr_converge_bugteam_enforcer.py +0 -311
- package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +0 -184
- package/hooks/blocking/test_pr_description_enforcer.py +0 -221
- package/hooks/blocking/test_pr_description_enforcer_body_audit.py +0 -247
- package/hooks/blocking/test_pr_description_enforcer_body_rules.py +0 -493
- package/hooks/blocking/test_pr_description_enforcer_command_parser.py +0 -366
- package/hooks/blocking/test_pr_description_enforcer_pr_number.py +0 -159
- package/hooks/blocking/test_pr_description_enforcer_proof_gate.py +0 -175
- package/hooks/blocking/test_pr_description_enforcer_readability.py +0 -443
- package/hooks/blocking/test_pr_description_proof_of_work.py +0 -313
- package/hooks/blocking/test_reviewer_spawn_gate.py +0 -230
- package/hooks/blocking/test_verdict_directory_write_blocker.py +0 -804
- package/hooks/blocking/test_verification_verdict_store.py +0 -974
- package/hooks/blocking/test_verified_commit_config_bootstrap.py +0 -67
- package/hooks/blocking/test_verified_commit_docs_delta.py +0 -176
- package/hooks/blocking/test_verified_commit_gate.py +0 -581
- package/hooks/blocking/test_verified_commit_gate_additional_context.py +0 -134
- package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +0 -131
- package/hooks/blocking/test_verifier_verdict_minter.py +0 -299
- package/hooks/blocking/tests/test_verified_commit_gate.py +0 -41
- package/hooks/blocking/verdict_directory_write_blocker.py +0 -687
- package/hooks/blocking/verification_verdict_store.py +0 -1039
- package/hooks/blocking/verified_commit_config_bootstrap.py +0 -63
- package/hooks/blocking/verified_commit_gate.py +0 -113
- package/hooks/blocking/verified_commit_gate_parts/CLAUDE.md +0 -28
- package/hooks/blocking/verified_commit_gate_parts/__init__.py +0 -1
- package/hooks/blocking/verified_commit_gate_parts/command_tokenization.py +0 -174
- package/hooks/blocking/verified_commit_gate_parts/deny_payload.py +0 -53
- package/hooks/blocking/verified_commit_gate_parts/deny_reason.py +0 -80
- package/hooks/blocking/verified_commit_gate_parts/directory_resolution.py +0 -170
- package/hooks/blocking/verified_commit_gate_parts/gated_invocations.py +0 -217
- package/hooks/blocking/verified_commit_gate_parts/tests/conftest.py +0 -10
- package/hooks/blocking/verified_commit_gate_parts/tests/test_command_tokenization.py +0 -94
- package/hooks/blocking/verified_commit_gate_parts/tests/test_deny_payload.py +0 -17
- package/hooks/blocking/verified_commit_gate_parts/tests/test_deny_reason.py +0 -38
- package/hooks/blocking/verified_commit_gate_parts/tests/test_directory_resolution.py +0 -71
- package/hooks/blocking/verified_commit_gate_parts/tests/test_gated_invocations.py +0 -96
- package/hooks/blocking/verified_commit_message_accuracy_blocker.py +0 -167
- package/hooks/blocking/verifier_verdict_minter.py +0 -280
- package/hooks/hooks_constants/code_verifier_spawn_preflight_gate_constants.py +0 -64
- package/hooks/hooks_constants/convergence_gate_blocker_constants.py +0 -53
- package/hooks/hooks_constants/pr_converge_bugteam_enforcer_constants.py +0 -55
- package/hooks/hooks_constants/pr_converge_bugteam_enforcer_state.py +0 -67
- package/hooks/hooks_constants/pr_description_enforcer_constants.py +0 -167
- package/hooks/hooks_constants/pr_description_proof_of_work_constants.py +0 -107
- package/hooks/hooks_constants/reviewer_spawn_gate_constants.py +0 -41
- package/hooks/hooks_constants/test_pr_description_enforcer_constants.py +0 -292
- package/hooks/lifecycle/pr_converge_bugteam_skill_tracker.py +0 -198
- package/hooks/lifecycle/test_pr_converge_bugteam_skill_tracker.py +0 -283
- package/rules/proof-of-work-pr-comments.md +0 -22
- package/rules/verified-commit-gate-skip.md +0 -4
- package/scripts/Show-Asset.ps1 +0 -106
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"""Regression tests for the verified-commit constants bootstrap.
|
|
2
|
-
|
|
3
|
-
These prove the shared constants module resolves to the sibling
|
|
4
|
-
``config/verified_commit_constants.py`` file even when a foreign ``config``
|
|
5
|
-
package sits ahead of ``blocking`` on ``sys.path``, and that a registration a
|
|
6
|
-
caller placed first is left untouched.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import subprocess
|
|
10
|
-
from collections.abc import Callable
|
|
11
|
-
|
|
12
|
-
RunUnderConfigShadow = Callable[[str], subprocess.CompletedProcess[str]]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def test_register_binds_dotted_name_to_sibling_constants_file(
|
|
16
|
-
run_under_config_shadow: RunUnderConfigShadow,
|
|
17
|
-
) -> None:
|
|
18
|
-
completed_probe = run_under_config_shadow(
|
|
19
|
-
"import verified_commit_config_bootstrap as bootstrap\n"
|
|
20
|
-
"bootstrap.register_verified_commit_constants()\n"
|
|
21
|
-
"import config.verified_commit_constants as loaded\n"
|
|
22
|
-
"print(loaded.__file__)\n"
|
|
23
|
-
"print(loaded.DETACHED_HEAD_LABEL)\n"
|
|
24
|
-
)
|
|
25
|
-
assert completed_probe.returncode == 0, completed_probe.stderr
|
|
26
|
-
assert "IS_DECOY_CONFIG" not in completed_probe.stdout
|
|
27
|
-
resolved_file_line, detached_head_line = completed_probe.stdout.splitlines()[:2]
|
|
28
|
-
assert resolved_file_line.replace("\\", "/").endswith(
|
|
29
|
-
"blocking/config/verified_commit_constants.py"
|
|
30
|
-
)
|
|
31
|
-
assert detached_head_line == "HEAD"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def test_register_binds_gate_output_constants_module(
|
|
35
|
-
run_under_config_shadow: RunUnderConfigShadow,
|
|
36
|
-
) -> None:
|
|
37
|
-
completed_probe = run_under_config_shadow(
|
|
38
|
-
"import verified_commit_config_bootstrap as bootstrap\n"
|
|
39
|
-
"bootstrap.register_verified_commit_constants()\n"
|
|
40
|
-
"import config.verified_commit_gate_output_constants as loaded\n"
|
|
41
|
-
"print(loaded.__file__)\n"
|
|
42
|
-
"print(loaded.DENY_PERMISSION_DECISION)\n"
|
|
43
|
-
)
|
|
44
|
-
assert completed_probe.returncode == 0, completed_probe.stderr
|
|
45
|
-
resolved_file_line, deny_decision_line = completed_probe.stdout.splitlines()[:2]
|
|
46
|
-
assert resolved_file_line.replace("\\", "/").endswith(
|
|
47
|
-
"blocking/config/verified_commit_gate_output_constants.py"
|
|
48
|
-
)
|
|
49
|
-
assert deny_decision_line == "deny"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def test_register_leaves_an_already_cached_module_untouched(
|
|
53
|
-
run_under_config_shadow: RunUnderConfigShadow,
|
|
54
|
-
) -> None:
|
|
55
|
-
completed_probe = run_under_config_shadow(
|
|
56
|
-
"import sys\n"
|
|
57
|
-
"import types\n"
|
|
58
|
-
"sentinel = types.ModuleType('config.verified_commit_constants')\n"
|
|
59
|
-
"sentinel.ORIGIN = 'caller-seeded'\n"
|
|
60
|
-
"sys.modules['config.verified_commit_constants'] = sentinel\n"
|
|
61
|
-
"import verified_commit_config_bootstrap as bootstrap\n"
|
|
62
|
-
"bootstrap.register_verified_commit_constants()\n"
|
|
63
|
-
"import config.verified_commit_constants as loaded\n"
|
|
64
|
-
"print(getattr(loaded, 'ORIGIN', 'displaced'))\n"
|
|
65
|
-
)
|
|
66
|
-
assert completed_probe.returncode == 0, completed_probe.stderr
|
|
67
|
-
assert completed_probe.stdout.strip().splitlines()[-1] == "caller-seeded"
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
"""Gate behavior for docs-only deltas and the cross-work-tree deny message.
|
|
2
|
-
|
|
3
|
-
Each test builds a real git repository with a real origin remote and drives
|
|
4
|
-
``deny_reason_for_directory`` — the same decision the verified_commit_gate hook
|
|
5
|
-
runs — so the docs-only exemption, the docs-after-verified-code block, and the
|
|
6
|
-
denial message's work-tree keying are asserted against live git state.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import importlib.util
|
|
10
|
-
import pathlib
|
|
11
|
-
import subprocess
|
|
12
|
-
import sys
|
|
13
|
-
|
|
14
|
-
import pytest
|
|
15
|
-
|
|
16
|
-
_HOOK_DIR = pathlib.Path(__file__).parent
|
|
17
|
-
if str(_HOOK_DIR) not in sys.path:
|
|
18
|
-
sys.path.insert(0, str(_HOOK_DIR))
|
|
19
|
-
|
|
20
|
-
gate_spec = importlib.util.spec_from_file_location(
|
|
21
|
-
"verified_commit_gate",
|
|
22
|
-
_HOOK_DIR / "verified_commit_gate.py",
|
|
23
|
-
)
|
|
24
|
-
assert gate_spec is not None
|
|
25
|
-
assert gate_spec.loader is not None
|
|
26
|
-
gate_module = importlib.util.module_from_spec(gate_spec)
|
|
27
|
-
gate_spec.loader.exec_module(gate_module)
|
|
28
|
-
deny_reason_for_directory = gate_module.deny_reason_for_directory
|
|
29
|
-
|
|
30
|
-
store_spec = importlib.util.spec_from_file_location(
|
|
31
|
-
"verification_verdict_store",
|
|
32
|
-
_HOOK_DIR / "verification_verdict_store.py",
|
|
33
|
-
)
|
|
34
|
-
assert store_spec is not None
|
|
35
|
-
assert store_spec.loader is not None
|
|
36
|
-
store_module = importlib.util.module_from_spec(store_spec)
|
|
37
|
-
store_spec.loader.exec_module(store_module)
|
|
38
|
-
resolve_merge_base = store_module.resolve_merge_base
|
|
39
|
-
branch_surface_manifest = store_module.branch_surface_manifest
|
|
40
|
-
manifest_sha256 = store_module.manifest_sha256
|
|
41
|
-
write_verdict = store_module.write_verdict
|
|
42
|
-
|
|
43
|
-
PRODUCTION_SOURCE = "def add(left: int, right: int) -> int:\n return left + right\n"
|
|
44
|
-
BEHAVIORAL_EDIT_SOURCE = "def add(left: int, right: int) -> int:\n return left - right\n"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def _run_git(repo_dir: pathlib.Path, *git_arguments: str) -> None:
|
|
48
|
-
subprocess.run(
|
|
49
|
-
["git", "-C", str(repo_dir), *git_arguments],
|
|
50
|
-
check=True,
|
|
51
|
-
capture_output=True,
|
|
52
|
-
text=True,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def _isolate_home(monkeypatch: pytest.MonkeyPatch, fake_home: pathlib.Path) -> None:
|
|
57
|
-
home_text = str(fake_home)
|
|
58
|
-
monkeypatch.setenv("HOME", home_text)
|
|
59
|
-
monkeypatch.setenv("USERPROFILE", home_text)
|
|
60
|
-
monkeypatch.delenv("HOMEDRIVE", raising=False)
|
|
61
|
-
monkeypatch.delenv("HOMEPATH", raising=False)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def _empty_hooks_dir(tmp_path: pathlib.Path) -> pathlib.Path:
|
|
65
|
-
hooks_dir = tmp_path / "nohooks"
|
|
66
|
-
hooks_dir.mkdir(exist_ok=True)
|
|
67
|
-
return hooks_dir
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def _empty_transcript(tmp_path: pathlib.Path) -> pathlib.Path:
|
|
71
|
-
transcript_path = tmp_path / "projects" / "demo" / "sess1.jsonl"
|
|
72
|
-
transcript_path.parent.mkdir(parents=True, exist_ok=True)
|
|
73
|
-
transcript_path.write_text("", encoding="utf-8")
|
|
74
|
-
return transcript_path
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def _init_pushed_repo(tmp_path: pathlib.Path) -> pathlib.Path:
|
|
78
|
-
origin_dir = tmp_path / "origin.git"
|
|
79
|
-
work_dir = tmp_path / "work"
|
|
80
|
-
work_dir.mkdir()
|
|
81
|
-
subprocess.run(
|
|
82
|
-
["git", "init", "--bare", "--initial-branch=main", str(origin_dir)],
|
|
83
|
-
check=True,
|
|
84
|
-
capture_output=True,
|
|
85
|
-
text=True,
|
|
86
|
-
)
|
|
87
|
-
_run_git(work_dir, "init", "--initial-branch=main")
|
|
88
|
-
_run_git(work_dir, "config", "user.email", "tests@example.com")
|
|
89
|
-
_run_git(work_dir, "config", "user.name", "Docs Delta Tests")
|
|
90
|
-
_run_git(work_dir, "config", "core.hooksPath", str(_empty_hooks_dir(tmp_path)))
|
|
91
|
-
(work_dir / "app.py").write_text(PRODUCTION_SOURCE, encoding="utf-8")
|
|
92
|
-
(work_dir / "README.md").write_text("# base\n", encoding="utf-8")
|
|
93
|
-
_run_git(work_dir, "add", "-A")
|
|
94
|
-
_run_git(work_dir, "commit", "-m", "base")
|
|
95
|
-
_run_git(work_dir, "remote", "add", "origin", str(origin_dir))
|
|
96
|
-
_run_git(work_dir, "push", "-u", "origin", "main")
|
|
97
|
-
return work_dir
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def _make_docs_only_repo(tmp_path: pathlib.Path) -> pathlib.Path:
|
|
101
|
-
work_dir = _init_pushed_repo(tmp_path)
|
|
102
|
-
(work_dir / "README.md").write_text("# base\n\nUpdated docs.\n", encoding="utf-8")
|
|
103
|
-
return work_dir
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _make_behavioral_code_repo(tmp_path: pathlib.Path) -> pathlib.Path:
|
|
107
|
-
work_dir = _init_pushed_repo(tmp_path)
|
|
108
|
-
(work_dir / "app.py").write_text(BEHAVIORAL_EDIT_SOURCE, encoding="utf-8")
|
|
109
|
-
return work_dir
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def _live_surface_hash(work_dir: pathlib.Path) -> str:
|
|
113
|
-
merge_base_sha = resolve_merge_base(str(work_dir))
|
|
114
|
-
assert merge_base_sha is not None
|
|
115
|
-
surface_manifest_text = branch_surface_manifest(str(work_dir), merge_base_sha)
|
|
116
|
-
assert surface_manifest_text is not None
|
|
117
|
-
return manifest_sha256(surface_manifest_text)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def test_pure_docs_only_branch_is_allowed_without_verdict(
|
|
121
|
-
monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
122
|
-
) -> None:
|
|
123
|
-
fake_home = tmp_path / "home"
|
|
124
|
-
fake_home.mkdir()
|
|
125
|
-
_isolate_home(monkeypatch, fake_home)
|
|
126
|
-
work_dir = _make_docs_only_repo(tmp_path)
|
|
127
|
-
transcript_path = _empty_transcript(tmp_path)
|
|
128
|
-
assert deny_reason_for_directory(str(work_dir), str(transcript_path)) is None
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def test_readme_change_after_verified_code_commit_is_denied(
|
|
132
|
-
monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
133
|
-
) -> None:
|
|
134
|
-
fake_home = tmp_path / "home"
|
|
135
|
-
fake_home.mkdir()
|
|
136
|
-
_isolate_home(monkeypatch, fake_home)
|
|
137
|
-
work_dir = _make_behavioral_code_repo(tmp_path)
|
|
138
|
-
code_surface_hash = _live_surface_hash(work_dir)
|
|
139
|
-
write_verdict(str(work_dir), code_surface_hash, True, [], "agent-x")
|
|
140
|
-
transcript_path = _empty_transcript(tmp_path)
|
|
141
|
-
assert deny_reason_for_directory(str(work_dir), str(transcript_path)) is None
|
|
142
|
-
_run_git(work_dir, "add", "-A")
|
|
143
|
-
_run_git(work_dir, "commit", "-m", "verified code change")
|
|
144
|
-
(work_dir / "README.md").write_text("# added after verification\n", encoding="utf-8")
|
|
145
|
-
deny_reason = deny_reason_for_directory(str(work_dir), str(transcript_path))
|
|
146
|
-
assert deny_reason is not None
|
|
147
|
-
assert "VERIFIED_COMMIT_GATE" in deny_reason
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def test_readme_added_beside_unverified_code_is_denied(
|
|
151
|
-
monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
152
|
-
) -> None:
|
|
153
|
-
fake_home = tmp_path / "home"
|
|
154
|
-
fake_home.mkdir()
|
|
155
|
-
_isolate_home(monkeypatch, fake_home)
|
|
156
|
-
work_dir = _make_behavioral_code_repo(tmp_path)
|
|
157
|
-
(work_dir / "README.md").write_text("# docs beside code\n", encoding="utf-8")
|
|
158
|
-
transcript_path = _empty_transcript(tmp_path)
|
|
159
|
-
deny_reason = deny_reason_for_directory(str(work_dir), str(transcript_path))
|
|
160
|
-
assert deny_reason is not None
|
|
161
|
-
assert "VERIFIED_COMMIT_GATE" in deny_reason
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
def test_deny_reason_for_directory_names_worktree_keying_and_remedy(
|
|
165
|
-
monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
166
|
-
) -> None:
|
|
167
|
-
fake_home = tmp_path / "home"
|
|
168
|
-
fake_home.mkdir()
|
|
169
|
-
_isolate_home(monkeypatch, fake_home)
|
|
170
|
-
work_dir = _make_behavioral_code_repo(tmp_path)
|
|
171
|
-
transcript_path = _empty_transcript(tmp_path)
|
|
172
|
-
deny_reason = deny_reason_for_directory(str(work_dir), str(transcript_path))
|
|
173
|
-
assert deny_reason is not None
|
|
174
|
-
lowered_reason = deny_reason.lower()
|
|
175
|
-
assert "work tree" in lowered_reason
|
|
176
|
-
assert "run this command from the work tree" in lowered_reason
|