claude-dev-env 2.36.0 → 4.1.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/skills/_shared/advisor/scripts/README.md +1 -1
- package/.agents/skills/syncing-submodules/SKILL.md +101 -0
- package/.agents/skills/syncing-submodules/reference/run-tasks.md +9 -0
- package/.agents/skills/syncing-submodules/scripts/submodule_sync.py +383 -0
- package/.agents/skills/syncing-submodules/scripts/submodule_sync_constants/__init__.py +1 -0
- package/.agents/skills/syncing-submodules/scripts/submodule_sync_constants/config/__init__.py +1 -0
- package/.agents/skills/syncing-submodules/scripts/submodule_sync_constants/config/constants.py +66 -0
- package/.agents/skills/syncing-submodules/scripts/sync_parent_pointer.py +88 -0
- package/.agents/skills/syncing-submodules/scripts/test_submodule_sync.py +303 -0
- package/.agents/skills/syncing-submodules/scripts/test_sync_parent_pointer.py +83 -0
- package/.agents/skills/team-advisor/SKILL.md +11 -11
- package/_shared/advisor/advisor-protocol.md +51 -51
- package/_shared/advisor/reference/advisor-block.md +9 -9
- package/_shared/advisor/reference/astra-rung.md +39 -0
- package/_shared/advisor/reference/identity.md +4 -4
- package/_shared/advisor/reference/lifecycle.md +6 -6
- package/_shared/advisor/reference/spawn-walk-log.md +9 -9
- package/_shared/advisor/reference/third-party-bind.md +11 -11
- package/_shared/advisor/reference/warm-up.md +13 -13
- package/_shared/advisor/scripts/codex_astra_advisor.py +308 -0
- package/_shared/advisor/scripts/codex_astra_preflight.py +115 -0
- package/_shared/advisor/scripts/codex_astra_reply.py +159 -0
- package/_shared/advisor/scripts/config/advisor_scripts_constants/advisor_route_constants.py +3 -3
- package/_shared/advisor/scripts/config/advisor_scripts_constants/astra_advisor_constants.py +38 -0
- package/_shared/advisor/scripts/model_tier_run_validator.py +17 -18
- package/_shared/advisor/scripts/tests/test_codex_astra_advisor.py +271 -0
- package/_shared/advisor/scripts/tests/test_codex_astra_preflight.py +24 -0
- package/_shared/advisor/scripts/tests/test_codex_astra_reply.py +42 -0
- package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +55 -30
- package/_shared/advisor/scripts/tests/test_tier_model_ids.py +14 -4
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +14 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +138 -50
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +13 -1
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/ever-shipped-skills.test.mjs +30 -0
- package/bin/git_hooks_installer.mjs +0 -1
- package/bin/git_hooks_installer.test.mjs +16 -1
- package/bin/install.mjs +5 -2
- package/bin/install.prune.test.mjs +36 -24
- package/bin/install.test.mjs +7 -0
- package/docs/references/team-advisor-skill.md +3 -3
- package/hooks/validators/README.md +35 -1
- package/package.json +1 -1
- package/scripts/check.ps1 +18 -6
- package/scripts/policy_lint/adapter_detectors.py +42 -2
- package/scripts/policy_lint/adapters.py +24 -0
- package/scripts/policy_lint/config/constants.py +11 -0
- package/scripts/policy_lint/engine.py +1 -1
- package/scripts/policy_lint/model.py +1 -0
- package/scripts/policy_lint/registry.py +10 -1
- package/scripts/repository_checks/__init__.py +1 -0
- package/scripts/repository_checks/claude_md.py +108 -0
- package/scripts/repository_checks/config/__init__.py +1 -0
- package/scripts/repository_checks/config/constants.py +150 -0
- package/scripts/repository_checks/env_var_documentation.py +243 -0
- package/scripts/repository_checks/hook_modules.py +34 -0
- package/scripts/repository_checks/models.py +37 -0
- package/scripts/repository_checks/package_inventory.py +118 -0
- package/scripts/repository_checks/pytest_testpaths.py +84 -0
- package/scripts/repository_checks/reporting.py +39 -0
- package/scripts/repository_checks/runner.py +93 -0
- package/scripts/repository_checks/tracked_secrets.py +147 -0
- package/scripts/repository_checks/tracked_tree.py +28 -0
- package/scripts/repository_policy.py +120 -0
- package/scripts/tests/repository_policy_test_support.py +89 -0
- package/scripts/tests/test_cde_lint.py +25 -1
- package/scripts/tests/test_claude_md.py +68 -0
- package/scripts/tests/test_env_var_documentation.py +133 -0
- package/scripts/tests/test_hook_modules.py +17 -0
- package/scripts/tests/test_models.py +26 -0
- package/scripts/tests/test_package_inventory.py +96 -0
- package/scripts/tests/test_policy_lint_rules_registry.py +117 -0
- package/scripts/tests/test_pytest_testpaths.py +66 -0
- package/scripts/tests/test_reporting.py +54 -0
- package/scripts/tests/test_repository_policy.py +71 -0
- package/scripts/tests/test_runner.py +59 -0
- package/scripts/tests/test_tracked_secrets.py +175 -0
- package/scripts/tests/test_tracked_tree.py +28 -0
- package/_shared/advisor/reference/sol-rung.md +0 -39
- package/_shared/advisor/scripts/codex_sol_advisor.py +0 -581
- package/_shared/advisor/scripts/config/advisor_scripts_constants/sol_advisor_constants.py +0 -38
- package/_shared/advisor/scripts/tests/test_codex_sol_advisor.py +0 -740
- package/hooks/git-hooks/post_commit.py +0 -241
- package/hooks/git-hooks/test_post_commit.py +0 -298
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Evaluate Codex usage before an Astra advisor request."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib
|
|
6
|
+
import json
|
|
7
|
+
import math
|
|
8
|
+
import subprocess
|
|
9
|
+
import sys
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from advisor_scripts_constants.astra_advisor_constants import (
|
|
15
|
+
ASTRA_FALLBACK_KIND_BROKEN,
|
|
16
|
+
ASTRA_FALLBACK_KIND_DECLINED,
|
|
17
|
+
ASTRA_PREFLIGHT_FAILURE_REASON,
|
|
18
|
+
ASTRA_PROBE_TIMEOUT_REASON,
|
|
19
|
+
ASTRA_USAGE_PROBE_TIMEOUT_SECONDS,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class AstraPreflight:
|
|
25
|
+
eligible: bool
|
|
26
|
+
percent_left: float | None
|
|
27
|
+
reason: str
|
|
28
|
+
fallback_kind: str | None = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _preflight_fallback(
|
|
32
|
+
reason: str, percent_left: float | None, fallback_kind: str
|
|
33
|
+
) -> AstraPreflight:
|
|
34
|
+
return AstraPreflight(False, percent_left, reason, fallback_kind)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _load_usage_gate(probe_path: Path) -> Callable[[float], bool]:
|
|
38
|
+
probe_directory = str(probe_path.parent)
|
|
39
|
+
if probe_directory not in sys.path:
|
|
40
|
+
sys.path.insert(0, probe_directory)
|
|
41
|
+
return importlib.import_module("codex_usage_probe").is_codex_review_required
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _parse_probe_percent(stdout_text: str) -> tuple[float | None, str | None]:
|
|
45
|
+
try:
|
|
46
|
+
report = json.loads(stdout_text)
|
|
47
|
+
except (TypeError, json.JSONDecodeError):
|
|
48
|
+
return None, "usage report is malformed"
|
|
49
|
+
if not isinstance(report, dict):
|
|
50
|
+
return None, "usage report is malformed"
|
|
51
|
+
raw_percent = report.get("percent_left")
|
|
52
|
+
if isinstance(raw_percent, bool) or not isinstance(raw_percent, (int, float)):
|
|
53
|
+
return None, "usage meter is unknown" if raw_percent is None else "usage meter is malformed"
|
|
54
|
+
percent_left = float(raw_percent)
|
|
55
|
+
if not math.isfinite(percent_left):
|
|
56
|
+
return None, "usage meter is malformed"
|
|
57
|
+
return percent_left, None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _run_probe(
|
|
61
|
+
probe_path: Path,
|
|
62
|
+
process_runner: Callable[..., subprocess.CompletedProcess[str]],
|
|
63
|
+
) -> subprocess.CompletedProcess[str]:
|
|
64
|
+
return process_runner(
|
|
65
|
+
[sys.executable, str(probe_path)],
|
|
66
|
+
capture_output=True,
|
|
67
|
+
text=True,
|
|
68
|
+
check=False,
|
|
69
|
+
shell=False,
|
|
70
|
+
timeout=ASTRA_USAGE_PROBE_TIMEOUT_SECONDS,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _preflight_from_probe(
|
|
75
|
+
probe_path: Path, completed: subprocess.CompletedProcess[str]
|
|
76
|
+
) -> AstraPreflight:
|
|
77
|
+
if completed.returncode != 0:
|
|
78
|
+
reason = f"{ASTRA_PREFLIGHT_FAILURE_REASON}: probe exit {completed.returncode}"
|
|
79
|
+
return _preflight_fallback(reason, None, ASTRA_FALLBACK_KIND_BROKEN)
|
|
80
|
+
percent_left, parse_reason = _parse_probe_percent(completed.stdout)
|
|
81
|
+
if parse_reason is not None or percent_left is None:
|
|
82
|
+
reason = f"{ASTRA_PREFLIGHT_FAILURE_REASON}: {parse_reason or 'usage meter is unknown'}"
|
|
83
|
+
return _preflight_fallback(reason, None, ASTRA_FALLBACK_KIND_BROKEN)
|
|
84
|
+
if not _load_usage_gate(probe_path)(percent_left):
|
|
85
|
+
reason = f"{ASTRA_PREFLIGHT_FAILURE_REASON}: usage meter is at or below the gate"
|
|
86
|
+
return _preflight_fallback(reason, percent_left, ASTRA_FALLBACK_KIND_DECLINED)
|
|
87
|
+
return AstraPreflight(True, percent_left, "usage meter is above the Astra gate")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def run_astra_preflight(
|
|
91
|
+
probe_path: Path,
|
|
92
|
+
process_runner: Callable[..., subprocess.CompletedProcess[str]],
|
|
93
|
+
) -> AstraPreflight:
|
|
94
|
+
"""Run the usage probe and decide whether Astra may bind.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
probe_path: Path to the installed usage probe.
|
|
98
|
+
process_runner: Callable that runs the probe.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Eligibility, remaining usage percent, reason, and fallback kind.
|
|
102
|
+
"""
|
|
103
|
+
try:
|
|
104
|
+
completed = _run_probe(probe_path, process_runner)
|
|
105
|
+
return _preflight_from_probe(probe_path, completed)
|
|
106
|
+
except subprocess.TimeoutExpired as error:
|
|
107
|
+
return _preflight_fallback(
|
|
108
|
+
f"{ASTRA_PROBE_TIMEOUT_REASON}: {error}", None, ASTRA_FALLBACK_KIND_BROKEN
|
|
109
|
+
)
|
|
110
|
+
except (OSError, subprocess.SubprocessError, ImportError, AttributeError, TypeError, ValueError) as error:
|
|
111
|
+
return _preflight_fallback(
|
|
112
|
+
f"{ASTRA_PREFLIGHT_FAILURE_REASON}: {error}",
|
|
113
|
+
None,
|
|
114
|
+
ASTRA_FALLBACK_KIND_BROKEN,
|
|
115
|
+
)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Parse Codex JSONL and build Astra advisor replies."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
from advisor_scripts_constants.advisor_route_constants import (
|
|
9
|
+
ADVISOR_FALLBACK_RESULT,
|
|
10
|
+
ADVISOR_FALLBACK_TIER,
|
|
11
|
+
ADVISOR_MODEL_TIER,
|
|
12
|
+
ALL_ADVISOR_GUIDANCE_SIGNALS,
|
|
13
|
+
CODEX_BIND_SUCCESS_TOKEN,
|
|
14
|
+
)
|
|
15
|
+
from advisor_scripts_constants.astra_advisor_constants import (
|
|
16
|
+
ASTRA_FALLBACK_KIND_BROKEN,
|
|
17
|
+
ASTRA_INVALID_SIGNAL_REASON,
|
|
18
|
+
ASTRA_MALFORMED_JSONL_REASON,
|
|
19
|
+
ASTRA_MISSING_SESSION_REASON,
|
|
20
|
+
ASTRA_REPLY_FAILURE_REASON,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class CodexAstraAdvisorReply:
|
|
26
|
+
session_id: str | None
|
|
27
|
+
guidance: str | None
|
|
28
|
+
successful: bool
|
|
29
|
+
reason: str | None
|
|
30
|
+
is_fallback: bool
|
|
31
|
+
signal: str | None
|
|
32
|
+
astra_enabled: bool
|
|
33
|
+
selected_tier: str
|
|
34
|
+
outcome: str
|
|
35
|
+
fallback_kind: str | None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def build_fallback_reply(
|
|
39
|
+
reason: str,
|
|
40
|
+
is_astra_enabled: bool,
|
|
41
|
+
fallback_kind: str | None = ASTRA_FALLBACK_KIND_BROKEN,
|
|
42
|
+
) -> CodexAstraAdvisorReply:
|
|
43
|
+
"""Build a failed advisor reply.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
reason: Why the request fell back.
|
|
47
|
+
is_astra_enabled: True when the Astra flag was on.
|
|
48
|
+
fallback_kind: Kind of fallback.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Failed reply with no session or guidance.
|
|
52
|
+
"""
|
|
53
|
+
return CodexAstraAdvisorReply(
|
|
54
|
+
None,
|
|
55
|
+
None,
|
|
56
|
+
False,
|
|
57
|
+
reason,
|
|
58
|
+
True,
|
|
59
|
+
None,
|
|
60
|
+
is_astra_enabled,
|
|
61
|
+
ADVISOR_FALLBACK_TIER,
|
|
62
|
+
ADVISOR_FALLBACK_RESULT,
|
|
63
|
+
fallback_kind,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def build_success_reply(
|
|
68
|
+
session_id: str, guidance: str, signal: str
|
|
69
|
+
) -> CodexAstraAdvisorReply:
|
|
70
|
+
"""Build a successful advisor reply.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
session_id: Codex session id.
|
|
74
|
+
guidance: Advisor text.
|
|
75
|
+
signal: First-line guidance signal.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Successful reply with Astra enabled.
|
|
79
|
+
"""
|
|
80
|
+
return CodexAstraAdvisorReply(
|
|
81
|
+
session_id,
|
|
82
|
+
guidance,
|
|
83
|
+
True,
|
|
84
|
+
None,
|
|
85
|
+
False,
|
|
86
|
+
signal,
|
|
87
|
+
True,
|
|
88
|
+
ADVISOR_MODEL_TIER,
|
|
89
|
+
CODEX_BIND_SUCCESS_TOKEN,
|
|
90
|
+
None,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _guidance_signal(guidance: str) -> str | None:
|
|
95
|
+
for each_line in guidance.splitlines():
|
|
96
|
+
candidate = each_line.strip()
|
|
97
|
+
if candidate:
|
|
98
|
+
return candidate if candidate in ALL_ADVISOR_GUIDANCE_SIGNALS else None
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _parse_event_line(each_line: str) -> tuple[str | None, str | None]:
|
|
103
|
+
event = json.loads(each_line)
|
|
104
|
+
if not isinstance(event, dict):
|
|
105
|
+
raise TypeError("event must be an object")
|
|
106
|
+
discovered_session_id: str | None = None
|
|
107
|
+
discovered_guidance: str | None = None
|
|
108
|
+
if event.get("type") == "thread.started":
|
|
109
|
+
raw_session = event.get("thread_id")
|
|
110
|
+
if isinstance(raw_session, str) and raw_session.strip():
|
|
111
|
+
discovered_session_id = raw_session.strip()
|
|
112
|
+
completed_event = event.get("item")
|
|
113
|
+
if event.get("type") == "item.completed" and isinstance(completed_event, dict):
|
|
114
|
+
message_text = completed_event.get("text")
|
|
115
|
+
if completed_event.get("type") == "agent_message" and isinstance(message_text, str):
|
|
116
|
+
discovered_guidance = message_text.strip()
|
|
117
|
+
return discovered_session_id, discovered_guidance
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _collect_reply_parts(jsonl_text: str) -> tuple[str | None, str | None]:
|
|
121
|
+
session_id: str | None = None
|
|
122
|
+
guidance: str | None = None
|
|
123
|
+
for each_line in jsonl_text.splitlines():
|
|
124
|
+
if each_line.strip():
|
|
125
|
+
discovered_session_id, discovered_guidance = _parse_event_line(each_line)
|
|
126
|
+
session_id = discovered_session_id or session_id
|
|
127
|
+
guidance = discovered_guidance or guidance
|
|
128
|
+
return session_id, guidance
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def parse_codex_jsonl_reply(
|
|
132
|
+
jsonl_text: str,
|
|
133
|
+
existing_session_id: str | None,
|
|
134
|
+
is_astra_enabled: bool,
|
|
135
|
+
fallback_kind: str | None = None,
|
|
136
|
+
) -> CodexAstraAdvisorReply:
|
|
137
|
+
"""Parse Codex JSONL into an Astra advisor reply.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
jsonl_text: JSONL from Codex stdout.
|
|
141
|
+
existing_session_id: Session expected on resume, or None on bind.
|
|
142
|
+
is_astra_enabled: True when the Astra flag was on.
|
|
143
|
+
fallback_kind: Kind of fallback on a failed reply.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Advisor reply, or a fallback.
|
|
147
|
+
"""
|
|
148
|
+
try:
|
|
149
|
+
session_id, guidance = _collect_reply_parts(jsonl_text)
|
|
150
|
+
except (TypeError, json.JSONDecodeError):
|
|
151
|
+
return build_fallback_reply(ASTRA_MALFORMED_JSONL_REASON, is_astra_enabled, fallback_kind)
|
|
152
|
+
if session_id is None or (existing_session_id is not None and session_id != existing_session_id):
|
|
153
|
+
return build_fallback_reply(ASTRA_MISSING_SESSION_REASON, is_astra_enabled, fallback_kind)
|
|
154
|
+
if not guidance:
|
|
155
|
+
return build_fallback_reply(ASTRA_REPLY_FAILURE_REASON, is_astra_enabled, fallback_kind)
|
|
156
|
+
signal = _guidance_signal(guidance)
|
|
157
|
+
if signal is None:
|
|
158
|
+
return build_fallback_reply(ASTRA_INVALID_SIGNAL_REASON, is_astra_enabled, fallback_kind)
|
|
159
|
+
return build_success_reply(session_id, guidance, signal)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"""Shared
|
|
1
|
+
"""Shared constants for advisor selection and replies."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
ADVISOR_MODEL_TIER: str = "
|
|
6
|
-
ADVISOR_CODEX_MODEL_ID: str = "gpt-
|
|
5
|
+
ADVISOR_MODEL_TIER: str = "Astra"
|
|
6
|
+
ADVISOR_CODEX_MODEL_ID: str = "gpt-6-astra"
|
|
7
7
|
ADVISOR_FALLBACK_TIER: str = "Fable"
|
|
8
8
|
ADVISOR_FALLBACK_RESULT: str = "fable"
|
|
9
9
|
ADVISOR_EFFORT_ENV_VAR: str = "ADVISOR_EFFORT"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Constants for the optional Codex Astra advisor bind."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
CODEX_EXECUTABLE: str = "codex"
|
|
6
|
+
ADVISOR_CODEX_EXECUTABLE_ENV_VAR: str = "ADVISOR_CODEX_EXECUTABLE"
|
|
7
|
+
CODEX_READ_ONLY_SANDBOX: str = "read-only"
|
|
8
|
+
CODEX_JSON_FLAG: str = "--json"
|
|
9
|
+
CODEX_MODEL_FLAG: str = "--model"
|
|
10
|
+
CODEX_CONFIG_FLAG: str = "--config"
|
|
11
|
+
CODEX_REASONING_CONFIG_TEMPLATE: str = 'model_reasoning_effort="{effort}"'
|
|
12
|
+
CODEX_PROMPT_FROM_STDIN: str = "-"
|
|
13
|
+
CODEX_EXEC_SUBCOMMAND: str = "exec"
|
|
14
|
+
CODEX_RESUME_SUBCOMMAND: str = "resume"
|
|
15
|
+
CODEX_SANDBOX_FLAG: str = "--sandbox"
|
|
16
|
+
CLAUDE_CONFIG_DIRECTORY_NAME: str = ".claude"
|
|
17
|
+
USAGE_PROBE_SHARED_DIRECTORY_NAME: str = "_shared"
|
|
18
|
+
USAGE_PROBE_PACKAGE_DIRECTORY_NAME: str = "pr-loop"
|
|
19
|
+
USAGE_PROBE_SCRIPTS_DIRECTORY_NAME: str = "scripts"
|
|
20
|
+
USAGE_PROBE_FILENAME: str = "codex_usage_probe.py"
|
|
21
|
+
ASTRA_SESSION_ID_METAVAR: str = "SESSION_ID"
|
|
22
|
+
ASTRA_CODEX_TIMEOUT_SECONDS: float = 120.0
|
|
23
|
+
ASTRA_USAGE_PROBE_TIMEOUT_SECONDS: float = 30.0
|
|
24
|
+
ASTRA_ENV_VAR: str = "ADVISOR_ASTRA"
|
|
25
|
+
ALL_ASTRA_TRUTHY_VALUES: frozenset[str] = frozenset({"1", "true", "yes", "on"})
|
|
26
|
+
ASTRA_PREFLIGHT_FAILURE_REASON: str = "astra preflight did not establish an eligible Codex meter"
|
|
27
|
+
ASTRA_BIND_FAILURE_REASON: str = "Codex Astra bind failed"
|
|
28
|
+
ASTRA_REPLY_FAILURE_REASON: str = "Codex Astra returned no advisor guidance"
|
|
29
|
+
ASTRA_PROBE_TIMEOUT_REASON: str = "Codex Astra meter check timed out"
|
|
30
|
+
ASTRA_CODEX_TIMEOUT_REASON: str = "Codex Astra request timed out"
|
|
31
|
+
ASTRA_MALFORMED_JSONL_REASON: str = "Codex Astra returned malformed JSONL"
|
|
32
|
+
ASTRA_MISSING_SESSION_REASON: str = "Codex Astra returned no session id"
|
|
33
|
+
ASTRA_INVALID_SIGNAL_REASON: str = "Codex Astra returned an invalid guidance signal"
|
|
34
|
+
ASTRA_EXECUTABLE_NOT_FOUND_REASON: str = "Codex Astra could not find the codex executable on PATH"
|
|
35
|
+
ASTRA_FALLBACK_KIND_DECLINED: str = "declined"
|
|
36
|
+
ASTRA_FALLBACK_KIND_BROKEN: str = "broken"
|
|
37
|
+
ASTRA_ENABLE_FLAG: str = "--enable-astra"
|
|
38
|
+
ASTRA_EFFORT_FLAG: str = "--effort"
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"""Mechanically validate a model-tier spawn-walk log.
|
|
2
2
|
|
|
3
3
|
The advisor protocol's Model floor section emits a structured spawn-walk log.
|
|
4
|
-
This validator reads that log back and checks its invariants.
|
|
5
|
-
from data, not inferred from a transcript.
|
|
4
|
+
This validator reads that log back and checks its invariants.
|
|
6
5
|
|
|
7
6
|
::
|
|
8
7
|
|
|
@@ -24,12 +23,12 @@ from data, not inferred from a transcript.
|
|
|
24
23
|
|
|
25
24
|
codex_bind = ModelTierRun(
|
|
26
25
|
own_tier="Opus",
|
|
27
|
-
candidate_tiers=["
|
|
28
|
-
attempts=[{"tier": "
|
|
29
|
-
selected_tier="
|
|
26
|
+
candidate_tiers=["Astra"],
|
|
27
|
+
attempts=[{"tier": "Astra", "result": "spawned"}],
|
|
28
|
+
selected_tier="Astra",
|
|
30
29
|
host_profile="Codex",
|
|
31
30
|
)
|
|
32
|
-
validate_model_tier_run(codex_bind) # ok: Codex in-session
|
|
31
|
+
validate_model_tier_run(codex_bind) # ok: Codex in-session Astra spawn
|
|
33
32
|
|
|
34
33
|
A run whose selected_tier is not the first successful bind fails.
|
|
35
34
|
On any broken invariant, validate_model_tier_run raises ModelTierRunError.
|
|
@@ -93,7 +92,7 @@ class ModelTierRun:
|
|
|
93
92
|
attempts: list[dict[str, str]]
|
|
94
93
|
selected_tier: str | None
|
|
95
94
|
fallback_reason: str | None = None
|
|
96
|
-
|
|
95
|
+
is_astra_enabled: bool = False
|
|
97
96
|
host_profile: str = HOST_PROFILE_CLAUDE
|
|
98
97
|
|
|
99
98
|
|
|
@@ -113,7 +112,7 @@ def _canonical_tier_list(all_tier_names: list[str]) -> list[str] | None:
|
|
|
113
112
|
|
|
114
113
|
def _expected_candidate_tiers(
|
|
115
114
|
own_tier: str,
|
|
116
|
-
|
|
115
|
+
is_astra_enabled: bool = False,
|
|
117
116
|
host_profile: str = HOST_PROFILE_CLAUDE,
|
|
118
117
|
) -> list[str]:
|
|
119
118
|
maybe_canonical_own_tier = canonical_tier_name(own_tier)
|
|
@@ -127,7 +126,7 @@ def _expected_candidate_tiers(
|
|
|
127
126
|
if maybe_canonical_host == HOST_PROFILE_CODEX:
|
|
128
127
|
return [ADVISOR_MODEL_TIER]
|
|
129
128
|
all_expected_candidates = [ADVISOR_FALLBACK_TIER]
|
|
130
|
-
if
|
|
129
|
+
if is_astra_enabled:
|
|
131
130
|
all_expected_candidates.append(ADVISOR_MODEL_TIER)
|
|
132
131
|
return all_expected_candidates
|
|
133
132
|
|
|
@@ -164,11 +163,11 @@ def validate_model_tier_run(run: ModelTierRun) -> None:
|
|
|
164
163
|
validate_model_tier_run(cli_bind) # ok: CLI Claude-chain bind
|
|
165
164
|
validate_model_tier_run(broken_log) # flag: ModelTierRunError
|
|
166
165
|
|
|
167
|
-
Candidate tiers are Fable, plus
|
|
168
|
-
Claude and ThirdParty hosts. A Codex host walks
|
|
169
|
-
``own_tier`` is recorded and must be a known tier
|
|
166
|
+
Candidate tiers are Fable, plus Astra when ``is_astra_enabled`` is true, on
|
|
167
|
+
Claude and ThirdParty hosts. A Codex host walks Astra only. Consumer
|
|
168
|
+
``own_tier`` is recorded and must be a known tier. It does not add Opus
|
|
170
169
|
to the advisor walk. Tries walk that list in order. Early stop only
|
|
171
|
-
after ``spawned``, ``cli``, or
|
|
170
|
+
after ``spawned``, ``cli``, or Astra ``codex`` (and Astra ``spawned`` on a
|
|
172
171
|
Codex host). A null selected_tier requires a full walk plus
|
|
173
172
|
fallback_reason.
|
|
174
173
|
|
|
@@ -183,7 +182,7 @@ def validate_model_tier_run(run: ModelTierRun) -> None:
|
|
|
183
182
|
"""
|
|
184
183
|
all_expected_candidates = _expected_candidate_tiers(
|
|
185
184
|
run.own_tier,
|
|
186
|
-
|
|
185
|
+
is_astra_enabled=run.is_astra_enabled,
|
|
187
186
|
host_profile=run.host_profile,
|
|
188
187
|
)
|
|
189
188
|
maybe_canonical_candidates = _canonical_tier_list(run.candidate_tiers)
|
|
@@ -257,9 +256,9 @@ def load_model_tier_run_from_json_path(from_path: Path) -> ModelTierRun:
|
|
|
257
256
|
TypeError: When a field has the wrong shape.
|
|
258
257
|
"""
|
|
259
258
|
parsed_payload = json.loads(from_path.read_text(encoding="utf-8"))
|
|
260
|
-
|
|
261
|
-
if not isinstance(
|
|
262
|
-
raise TypeError("
|
|
259
|
+
raw_astra_enabled = parsed_payload.get("astra_enabled", False)
|
|
260
|
+
if not isinstance(raw_astra_enabled, bool):
|
|
261
|
+
raise TypeError("astra_enabled must be a boolean")
|
|
263
262
|
raw_host_profile = parsed_payload.get(HOST_PROFILE_JSON_KEY, HOST_PROFILE_CLAUDE)
|
|
264
263
|
if not isinstance(raw_host_profile, str):
|
|
265
264
|
raise TypeError(HOST_PROFILE_MUST_BE_STRING_MESSAGE)
|
|
@@ -269,7 +268,7 @@ def load_model_tier_run_from_json_path(from_path: Path) -> ModelTierRun:
|
|
|
269
268
|
attempts=list(parsed_payload["attempts"]),
|
|
270
269
|
selected_tier=parsed_payload.get("selected_tier"),
|
|
271
270
|
fallback_reason=parsed_payload.get("fallback_reason"),
|
|
272
|
-
|
|
271
|
+
is_astra_enabled=raw_astra_enabled,
|
|
273
272
|
host_profile=raw_host_profile,
|
|
274
273
|
)
|
|
275
274
|
|