diff --git a/plugins/claude-code/scripts/run-sleep.sh b/plugins/claude-code/scripts/run-sleep.sh index e46e212..310d8de 100755 --- a/plugins/claude-code/scripts/run-sleep.sh +++ b/plugins/claude-code/scripts/run-sleep.sh @@ -30,12 +30,17 @@ if [ -z "${REPO_ROOT:-}" ]; then fi PY="" -for cand in python3.12 python3.11 python3.10 python3; do - if command -v "$cand" >/dev/null 2>&1; then - ver="$("$cand" -c 'import sys; print("%d%d" % sys.version_info[:2])' 2>/dev/null || echo 0)" - if [ "${ver:-0}" -ge 310 ]; then PY="$cand"; break; fi - fi -done +# Allow explicit Python override (useful on macOS with old system Python). +if [ -n "${SKILLOPT_SLEEP_PYTHON:-}" ]; then + PY="$SKILLOPT_SLEEP_PYTHON" +else + for cand in python3.12 python3.11 python3.10 python3; do + if command -v "$cand" >/dev/null 2>&1; then + ver="$("$cand" -c 'import sys; print("%d%d" % sys.version_info[:2])' 2>/dev/null || echo 0)" + if [ "${ver:-0}" -ge 310 ]; then PY="$cand"; break; fi + fi + done +fi if [ -z "$PY" ]; then echo "[sleep] ERROR: need Python >= 3.10 (found none)." >&2 exit 1 diff --git a/plugins/run-sleep.sh b/plugins/run-sleep.sh index e46e212..310d8de 100755 --- a/plugins/run-sleep.sh +++ b/plugins/run-sleep.sh @@ -30,12 +30,17 @@ if [ -z "${REPO_ROOT:-}" ]; then fi PY="" -for cand in python3.12 python3.11 python3.10 python3; do - if command -v "$cand" >/dev/null 2>&1; then - ver="$("$cand" -c 'import sys; print("%d%d" % sys.version_info[:2])' 2>/dev/null || echo 0)" - if [ "${ver:-0}" -ge 310 ]; then PY="$cand"; break; fi - fi -done +# Allow explicit Python override (useful on macOS with old system Python). +if [ -n "${SKILLOPT_SLEEP_PYTHON:-}" ]; then + PY="$SKILLOPT_SLEEP_PYTHON" +else + for cand in python3.12 python3.11 python3.10 python3; do + if command -v "$cand" >/dev/null 2>&1; then + ver="$("$cand" -c 'import sys; print("%d%d" % sys.version_info[:2])' 2>/dev/null || echo 0)" + if [ "${ver:-0}" -ge 310 ]; then PY="$cand"; break; fi + fi + done +fi if [ -z "$PY" ]; then echo "[sleep] ERROR: need Python >= 3.10 (found none)." >&2 exit 1 diff --git a/skillopt_sleep/__main__.py b/skillopt_sleep/__main__.py index 78f22f3..608487a 100644 --- a/skillopt_sleep/__main__.py +++ b/skillopt_sleep/__main__.py @@ -76,7 +76,8 @@ def _add_common(p: argparse.ArgumentParser) -> None: p.add_argument("--codex-home", default="", help="override ~/.codex for archived session harvest") p.add_argument("--source", default="", choices=["", "claude", "codex", "auto"], help="session transcript source") - p.add_argument("--lookback-hours", type=int, default=0) + p.add_argument("--lookback-hours", type=int, default=None, + help="harvest window in hours; 0 = scan full history") p.add_argument("--edit-budget", type=int, default=0) p.add_argument("--max-sessions", type=int, default=0, help="cap harvested sessions before mining; default derives from max tasks") @@ -111,8 +112,9 @@ def _cfg_from_args(args, task_meta: Dict[str, Any] | None = None) -> Any: overrides["codex_home"] = os.path.abspath(args.codex_home) if getattr(args, "source", ""): overrides["transcript_source"] = args.source - if getattr(args, "lookback_hours", 0): - overrides["lookback_hours"] = args.lookback_hours + lh = getattr(args, "lookback_hours", None) + if lh is not None: # --lookback-hours was explicitly passed (0 = full history) + overrides["lookback_hours"] = lh if getattr(args, "edit_budget", 0): overrides["edit_budget"] = args.edit_budget if getattr(args, "max_sessions", 0): diff --git a/skillopt_sleep/cycle.py b/skillopt_sleep/cycle.py index 4678cff..57b06a9 100644 --- a/skillopt_sleep/cycle.py +++ b/skillopt_sleep/cycle.py @@ -144,6 +144,15 @@ def run_sleep_cycle( _progress(cfg, f"using {len(tasks)} seeded tasks") else: since = state.last_harvest_for(project) + # On first run (no prior harvest), apply lookback_hours so we don't + # scan the entire transcript history and trigger massive LLM mining. + if since is None: + lookback_hours = cfg.get("lookback_hours", 72) + if lookback_hours is not None and lookback_hours > 0: + import time + ref_time = clock if clock is not None else time.time() + cutoff = ref_time - lookback_hours * 3600 + since = _now_iso(cutoff) max_tasks = cfg.get("max_tasks_per_night", 40) max_sessions = cfg.get("max_sessions_per_night", 0) or max_tasks * 3 candidate_limit = max_tasks diff --git a/skillopt_sleep/harvest.py b/skillopt_sleep/harvest.py index 3645d3f..851e5f1 100644 --- a/skillopt_sleep/harvest.py +++ b/skillopt_sleep/harvest.py @@ -294,6 +294,9 @@ def harvest( if not _project_matches(d.project or "", scope, invoked_project): continue if since_iso and d.ended_at and d.ended_at < since_iso: + # Note: files are sorted by mtime but we compare the embedded + # ended_at timestamp — mtime can diverge (copy/touch), so we + # cannot break here; we must continue to check all files. continue digests.append(d) if limit and len(digests) >= limit: