mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 19:07:17 +01:00
Merge branch 'worktree-agent-a179fa4cf3532a65f'
This commit is contained in:
commit
99f4e171e3
@ -102,9 +102,14 @@ def step2_attempts(events: list[dict[str, Any]]) -> int:
|
||||
|
||||
A ``fail`` (the list read as code, or named an operation) never reaches
|
||||
the checker, so it has no ``req_check``; a ``partial`` does, and is
|
||||
already counted there. CLI and app count one file alike.
|
||||
already counted there. CLI and app count one file alike. A force
|
||||
repeats the last try's grade but is not a try, so it is not counted.
|
||||
"""
|
||||
fails = sum(1 for e in _step2_grades(events) if e.get("grade") == "fail")
|
||||
fails = sum(
|
||||
1
|
||||
for e in _step2_grades(events)
|
||||
if e.get("grade") == "fail" and e.get("forced") is not True
|
||||
)
|
||||
return req_state(events).tries + fails
|
||||
|
||||
|
||||
|
||||
@ -5,9 +5,9 @@ Reads ``$FAKE_CLAUDE_DIR/script.json``: ``{"haiku": [...], "coach": [...]}``.
|
||||
A call made with ``--model haiku`` is the checker; any other is the coach.
|
||||
Each call takes the next answer of its kind -- ``{"result": "..."}`` is printed
|
||||
the way ``--output-format json`` prints it, ``{"exit": n, "stderr": "..."}``
|
||||
fails -- and appends ``{"kind", "args", "prompt"}`` to ``calls.jsonl`` so a
|
||||
test can prove what did and did not reach the model, and with which
|
||||
``LEETCODE_COACH_LOG`` in its env.
|
||||
fails, ``"sleep": s`` delays either (a slow turn) -- and appends
|
||||
``{"kind", "args", "prompt"}`` to ``calls.jsonl`` so a test can prove what did
|
||||
and did not reach the model, and with which ``LEETCODE_COACH_LOG`` in its env.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@ -16,6 +16,7 @@ import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def main() -> int:
|
||||
@ -33,6 +34,7 @@ def main() -> int:
|
||||
counter.write_text(str(used + 1), encoding="utf-8")
|
||||
script = json.loads((root / "script.json").read_text(encoding="utf-8"))
|
||||
answer = script[kind][used]
|
||||
time.sleep(float(answer.get("sleep", 0)))
|
||||
if "exit" in answer:
|
||||
sys.stderr.write(answer.get("stderr", ""))
|
||||
return int(answer["exit"])
|
||||
|
||||
68
leetcode_coach/leetcode_coach/tests/_live_relay.py
Normal file
68
leetcode_coach/leetcode_coach/tests/_live_relay.py
Normal file
@ -0,0 +1,68 @@
|
||||
"""Dev harness: the real relay on loopback, every outside dependency faked.
|
||||
|
||||
``python3 -m leetcode_coach.tests._live_relay PORT DIR [PACE_S]`` serves the
|
||||
real `Relay` (lane, backend, HTTP API, phone mirror) on ``127.0.0.1:PORT``
|
||||
so the app's own transport can be driven against it
|
||||
(``app/tool/coach_live_check.sh``). Faked, so nothing real is read or
|
||||
written: claude (``LEETCODE_CLAUDE_BIN``, set by the caller), the statement
|
||||
fetch, the LeetCode Accepted probe, Anki (dry run), Ollama (the discard
|
||||
port) and Firebase (an in-process `FakeRtdb`). Session logs and the relay's
|
||||
own files go under ``DIR``. Writes ``DIR/ready`` once listening and runs
|
||||
until SIGTERM / SIGINT.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import sys
|
||||
|
||||
from leetcode_coach import local_backend, progress
|
||||
from leetcode_coach.relay.app import Relay
|
||||
from leetcode_coach.relay.coach import Deps
|
||||
from leetcode_coach.relay.probe import AcceptedProbe
|
||||
from leetcode_coach.relay.rtdb import Rtdb
|
||||
from leetcode_coach.tests._fake_rtdb import FakeRtdb
|
||||
from leetcode_coach.tests._relay_statements import MISSING_NUMBER
|
||||
from leetcode_coach.tests._relay_support import FakeProbe
|
||||
|
||||
DEAD_OLLAMA = "http://127.0.0.1:9"
|
||||
REAL_PORT = 8777
|
||||
WITH_PACE = 3
|
||||
USAGE = "usage: _live_relay PORT DIR [PACE_S]"
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
"""Serve until a signal; 2 on bad arguments."""
|
||||
if len(argv) not in {WITH_PACE - 1, WITH_PACE} or not argv[0].isdigit():
|
||||
sys.stderr.write(USAGE + "\n")
|
||||
return 2
|
||||
port, root = int(argv[0]), Path(argv[1])
|
||||
if port == REAL_PORT:
|
||||
sys.stderr.write("refusing the real relay's port\n")
|
||||
return 2
|
||||
pace = float(argv[2]) if len(argv) == WITH_PACE else 3.0
|
||||
os.environ[progress.SESSIONS_ENV] = str(root / "sessions")
|
||||
local_backend.OLLAMA_URL = DEAD_OLLAMA
|
||||
deps = Deps(
|
||||
state_dir=root / "relay",
|
||||
fetch=lambda _slug: ("Missing Number", MISSING_NUMBER),
|
||||
probe=AcceptedProbe(FakeProbe()),
|
||||
cards_dry_run=True,
|
||||
)
|
||||
relay = Relay(deps, port=port, pace_s=pace)
|
||||
fake = FakeRtdb.start()
|
||||
signal.signal(signal.SIGTERM, lambda *_: relay.stop_event.set())
|
||||
signal.signal(signal.SIGINT, lambda *_: relay.stop_event.set())
|
||||
relay.start()
|
||||
relay.link_phone(Rtdb(fake.url, lambda: "live-check"))
|
||||
(root / "ready").write_text(str(relay.port), encoding="utf-8")
|
||||
relay.stop_event.wait()
|
||||
relay.stop()
|
||||
fake.stop()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
@ -84,6 +84,16 @@ def test_step_two_attempts_count_incomplete_lists_and_fail_grades() -> None:
|
||||
assert phase.step2_attempts(events) == 3
|
||||
|
||||
|
||||
def test_a_force_is_not_a_step_two_try() -> None:
|
||||
"""A force repeats the last try's grade (`fail`); it is no try itself.
|
||||
|
||||
Measured against the live relay 2026-10-23: three named-a-tool fails and
|
||||
a force showed ``attempts: 4`` in the state.
|
||||
"""
|
||||
fails = [_grade(2, "fail"), _grade(2, "fail"), _grade(2, "fail")]
|
||||
assert phase.step2_attempts([*fails, _grade(2, "fail", forced=True)]) == 3
|
||||
|
||||
|
||||
def _gate(log: Path, answers: list[bool] | None = None) -> phase.PhaseGate:
|
||||
asked: list[str] = []
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user