claude-dev-env 8.54.6 → 8.54.8
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/bin/install.test.mjs +4 -0
- package/package.json +1 -1
- package/scripts/account_broker.py +9 -5
- package/scripts/ci/install-playtest.test.mjs +2 -0
- package/scripts/claude_account_worker.py +2 -5
- package/scripts/dev_env_scripts_constants/account_broker_constants.py +1 -0
- package/scripts/dev_env_scripts_constants/claude_account_worker_constants.py +0 -6
- package/scripts/dev_env_scripts_constants/test_account_broker_constants.py +8 -1
- package/scripts/test_account_broker.py +4 -3
- package/scripts/test_claude_account_worker.py +1 -1
package/bin/install.test.mjs
CHANGED
|
@@ -2986,6 +2986,10 @@ test('the help output states that the installer reads only flags', () => {
|
|
|
2986
2986
|
assert.equal(helpRun.status, 0, helpRun.stderr);
|
|
2987
2987
|
assert.match(helpRun.stdout, /reads only flags/i);
|
|
2988
2988
|
assert.match(helpRun.stdout, /bare path argument carries no meaning/i);
|
|
2989
|
+
assert.match(
|
|
2990
|
+
helpRun.stdout,
|
|
2991
|
+
/--update\s+Full install: copy the package over the prior install, then prune files it no longer ships/,
|
|
2992
|
+
);
|
|
2989
2993
|
});
|
|
2990
2994
|
|
|
2991
2995
|
|
package/package.json
CHANGED
|
@@ -48,6 +48,7 @@ from dev_env_scripts_constants.account_broker_constants import (
|
|
|
48
48
|
ALL_PARENT_CLAUDE_SESSION_VARIABLES,
|
|
49
49
|
COMMAND_MISSING_EXIT_CODE,
|
|
50
50
|
REPORT_INDENT_SPACES,
|
|
51
|
+
TIMEOUT_EXIT_CODE,
|
|
51
52
|
WAIT_EXIT_CODE,
|
|
52
53
|
utc_time_text as _time_text,
|
|
53
54
|
)
|
|
@@ -287,13 +288,16 @@ def _attempt_once(context: _RunContext, decision: Decision) -> JobOutcome | None
|
|
|
287
288
|
account = decision.account
|
|
288
289
|
try:
|
|
289
290
|
completion = _invoke(context, account)
|
|
290
|
-
except
|
|
291
|
-
|
|
292
|
-
|
|
291
|
+
except subprocess.TimeoutExpired as error:
|
|
292
|
+
_record_spent_attempt(context, account, "timeout", TIMEOUT_EXIT_CODE)
|
|
293
|
+
context.report.final_decision = decision
|
|
294
|
+
return JobOutcome(TIMEOUT_EXIT_CODE, "", str(error), account.name, tuple(context.all_attempts), "timeout", None, None)
|
|
295
|
+
except OSError as error:
|
|
296
|
+
_record_spent_attempt(context, account, "start_failed", COMMAND_MISSING_EXIT_CODE)
|
|
293
297
|
context.start_failure_text = str(error)
|
|
294
|
-
if
|
|
298
|
+
if not context.all_readings:
|
|
295
299
|
context.report.final_decision = decision
|
|
296
|
-
final_status = "advisor_blocked" if context.product is Product.CLAUDE else
|
|
300
|
+
final_status = "advisor_blocked" if context.product is Product.CLAUDE else "start_failed"
|
|
297
301
|
return JobOutcome(COMMAND_MISSING_EXIT_CODE, "", str(error), account.name, tuple(context.all_attempts), final_status, None, None)
|
|
298
302
|
return None
|
|
299
303
|
combined = f"{completion.stdout}{completion.stderr}".casefold()
|
|
@@ -30,6 +30,8 @@ test('the driver reads an envelope from every stage of a fresh install, and repo
|
|
|
30
30
|
assert.match(greenRun.stdout, /\[PASS\] playtest install .* sha256=[0-9a-f]{64}/);
|
|
31
31
|
assert.match(greenRun.stdout, /\[PASS\] playtest session_start_hook .* sha256=[0-9a-f]{64}/);
|
|
32
32
|
assert.match(greenRun.stdout, /\[PASS\] playtest blocking_hook .* sha256=[0-9a-f]{64}/);
|
|
33
|
+
const blockingEnvelope = JSON.parse(readFileSync(join(evidenceDirectory, 'blocking_hook.json'), 'utf8'));
|
|
34
|
+
assert.equal(Object.hasOwn(blockingEnvelope, 'permissionDecision'), false);
|
|
33
35
|
assert.ok(
|
|
34
36
|
readFileSync(join(scratchHome, SANDBOX_GIT_CONFIG_NAME), 'utf8').startsWith(SANDBOX_GIT_CONFIG_BODY),
|
|
35
37
|
);
|
|
@@ -27,8 +27,6 @@ from dev_env_scripts_constants.claude_account_worker_constants import (
|
|
|
27
27
|
PROMPT_FILE_FLAG,
|
|
28
28
|
REPORT_FILE_FLAG,
|
|
29
29
|
SINGLE_PROMPT_FLAG,
|
|
30
|
-
TIMEOUT_ATTEMPT_STATUS,
|
|
31
|
-
TIMEOUT_EXIT_CODE,
|
|
32
30
|
TIMEOUT_MINUTES_FLAG,
|
|
33
31
|
UTF8_ENCODING,
|
|
34
32
|
)
|
|
@@ -104,11 +102,10 @@ def run_worker(
|
|
|
104
102
|
if outcome.status in {"wait", "exhausted"}:
|
|
105
103
|
report = wait_report("wait", _wait_reason(outcome), outcome.wait_reset_at)
|
|
106
104
|
return finalize_report(report_file, report)
|
|
107
|
-
is_timed_out = bool(outcome.attempts) and outcome.attempts[-1][1] == TIMEOUT_ATTEMPT_STATUS
|
|
108
105
|
report = make_report(
|
|
109
106
|
outcome.account_name or "none",
|
|
110
|
-
|
|
111
|
-
exit_code=
|
|
107
|
+
outcome.status,
|
|
108
|
+
exit_code=outcome.returncode,
|
|
112
109
|
duration_seconds=duration_seconds,
|
|
113
110
|
stdout_text=outcome.stdout,
|
|
114
111
|
)
|
|
@@ -13,10 +13,6 @@ MINIMUM_TIMEOUT_MINUTES: int = 1
|
|
|
13
13
|
|
|
14
14
|
LAUNCH_FAILURE_EXIT_CODE: int = 1
|
|
15
15
|
|
|
16
|
-
TIMEOUT_EXIT_CODE: int = 124
|
|
17
|
-
|
|
18
|
-
TIMEOUT_ATTEMPT_STATUS: str = "timeout"
|
|
19
|
-
|
|
20
16
|
CONFIGURATION_FAILURE_EXIT_CODE: int = 2
|
|
21
17
|
|
|
22
18
|
WAIT_DURATION_SECONDS: float = 0.0
|
|
@@ -104,8 +100,6 @@ __all__ = [
|
|
|
104
100
|
"SINGLE_PROMPT_FLAG",
|
|
105
101
|
"STDOUT_TAIL_CHARACTER_LIMIT",
|
|
106
102
|
"SUMMARY_LINE_TEMPLATE",
|
|
107
|
-
"TIMEOUT_ATTEMPT_STATUS",
|
|
108
|
-
"TIMEOUT_EXIT_CODE",
|
|
109
103
|
"TIMEOUT_MINUTES_FLAG",
|
|
110
104
|
"UTF8_ENCODING",
|
|
111
105
|
"WAIT_DURATION_SECONDS",
|
|
@@ -16,9 +16,11 @@ import pytest
|
|
|
16
16
|
|
|
17
17
|
from dev_env_scripts_constants import account_broker_constants as broker_constants
|
|
18
18
|
from dev_env_scripts_constants.account_broker_constants import (
|
|
19
|
+
ALL_BATCH_FILE_EXTENSIONS,
|
|
19
20
|
ALL_CLAUDE_FLOORS,
|
|
20
|
-
ALL_PARENT_CLAUDE_SESSION_VARIABLES,
|
|
21
21
|
ALL_CODEX_FLOORS,
|
|
22
|
+
ALL_PARENT_CLAUDE_SESSION_VARIABLES,
|
|
23
|
+
CMD_SHELL_METACHARACTERS,
|
|
22
24
|
JobOutcome,
|
|
23
25
|
)
|
|
24
26
|
from dev_env_scripts_constants.claude_account_constants import (
|
|
@@ -53,6 +55,11 @@ def test_should_keep_codex_floors_tied_to_the_tier_limits() -> None:
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
|
|
58
|
+
def test_batch_command_boundaries_include_shell_metacharacters() -> None:
|
|
59
|
+
assert ALL_BATCH_FILE_EXTENSIONS == frozenset({".bat", ".cmd"})
|
|
60
|
+
assert set(CMD_SHELL_METACHARACTERS) == set('&|<>^%!"\r\n')
|
|
61
|
+
|
|
62
|
+
|
|
56
63
|
def test_should_freeze_job_outcome() -> None:
|
|
57
64
|
outcome = JobOutcome(0, "", "", None, (), "served", None, None)
|
|
58
65
|
with pytest.raises(dataclasses.FrozenInstanceError):
|
|
@@ -687,6 +687,7 @@ def test_should_stop_after_timeout_without_running_job_again(
|
|
|
687
687
|
assert invoked_homes == ["first"]
|
|
688
688
|
assert outcome.attempts == (("first", "timeout"),)
|
|
689
689
|
assert outcome.status == "timeout"
|
|
690
|
+
assert outcome.returncode == 124
|
|
690
691
|
assert outcome.account_name == "first"
|
|
691
692
|
assert report.final_decision.account.name == "first"
|
|
692
693
|
assert account_broker.main(("choose", "--product", "codex")) == 0
|
|
@@ -696,12 +697,12 @@ def test_should_stop_after_timeout_without_running_job_again(
|
|
|
696
697
|
@pytest.mark.parametrize(
|
|
697
698
|
("product", "roster_names", "start_error", "expected_code"),
|
|
698
699
|
(
|
|
699
|
-
(Product.CLAUDE, ("first",), subprocess.TimeoutExpired("job", 1),
|
|
700
|
-
(Product.CODEX, ("first",), subprocess.TimeoutExpired("job", 1),
|
|
700
|
+
(Product.CLAUDE, ("first",), subprocess.TimeoutExpired("job", 1), 124),
|
|
701
|
+
(Product.CODEX, ("first",), subprocess.TimeoutExpired("job", 1), 124),
|
|
701
702
|
(Product.CODEX, (), OSError("missing command"), 127),
|
|
702
703
|
),
|
|
703
704
|
)
|
|
704
|
-
def
|
|
705
|
+
def test_should_exit_with_job_failure_code(
|
|
705
706
|
monkeypatch: pytest.MonkeyPatch,
|
|
706
707
|
tmp_path: Path,
|
|
707
708
|
product: Product,
|
|
@@ -165,7 +165,7 @@ def test_should_preserve_served_failure_code(
|
|
|
165
165
|
def test_should_exit_124_with_timeout_reason_when_the_broker_attempt_timed_out(
|
|
166
166
|
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
167
167
|
) -> None:
|
|
168
|
-
timed_out = JobOutcome(
|
|
168
|
+
timed_out = JobOutcome(124, "", "timed out", "extra_2", (("extra_2", "timeout"),), "timeout", None, None)
|
|
169
169
|
|
|
170
170
|
exit_code, report, _ = _run_worker(monkeypatch, tmp_path, timed_out)
|
|
171
171
|
|