by yukineko
v0.5.27: ctxrot now follows the SHARED autonomy switch (harness_core::autonomy, written by `condukt state autonomy-set`) instead of ignoring it. `Config::load` applies the switch as a DEFAULT LAYER below both the config file and the env: with the switch on and nothing configured, `auto_distill_on_band` and `auto_compact_enabled` both read true, but an explicit config.toml value or `CTXROT_AUTO_COMPACT` / `CTXROT_AUTO_DISTILL_ON_BAND` always wins -- one switch must never override an explicit human decision. New `ctxrot autonomy` prints `{"autonomous":b,"auto_distill_on_band":b,"auto_compact_enabled":b,"source":s}` and exits 0 (a report, not a gate). A switch file that exists but cannot be read is fail-closed: `autonomous:false`, `source:"undetermined-switch-file"` and a stderr warning naming it -- never a silent off. v0.5.22: new `ctxrot handoff-record` (PostToolUse:Read) / `ctxrot handoff` (PreToolUse:Task) hooks address one measured pattern from real session transcripts — a parent session Reads a large file, then dispatches a Task/subagent whose prompt concerns that same file, and the subagent pays for a redundant fresh Read of content the parent already has. handoff-record caches a Read's content (session_id + resolved absolute path + content, capped per-entry, bounded ring buffer on disk) once it clears a size floor; handoff matches a dispatching Task's prompt against that session's cached paths (substring match only — never a bare filename, and never across sessions, since there is no sibling-to-sibling correlation id in the hook payload) and splices the cached content into the prompt via `hookSpecificOutput.updatedInput`, so the subagent's first Read becomes unnecessary. This does NOT reduce total resident tokens system-wide — the content still occupies the subagent's context exactly once either way — it only avoids the wasted round trip and a subagent walking into preguard's size gate with no recourse; docs are explicit that this is not a token-count win. True concurrent sibling-subagent deduplication was investigated and found structurally infeasible via Claude Code's current hook API (confirmed: no parent_tool_use_id/batch-correlation field exists in PreToolUse/PostToolUse payloads) and was deliberately NOT attempted. bin/ctxrot (the POSIX launcher)'s missing-binary fallback gained the two new subcommands to its non-verdict exit-0 branch (they were previously absent and would have fallen through to the CLI-command `exit 1` default, which would have broken PreToolUse:Task on a host with no bundled binary); tests/launcher_missing_binary.rs's observability-hooks test now covers both. v0.5.21: `bin/ctxrot` (the POSIX launcher) no longer maps a MISSING per-platform binary to a blanket silent `exit 0`. A missing build means the check did not run, and exit-0-with-no-output is byte-identical to a clean run, so every verdict-bearing subcommand silently read as "nothing to flag": preguard granted the load gate, toolguard let an unmeasured payload through, stop ended the turn as if the budget check had passed, and statusline rendered the blank bar that reads as headroom (the 3b1eb24 fail-open). Each now resolves the cannot-determine on the restrictive side of its OWN protocol — preguard emits permissionDecision `ask` (a refusal to guess, not a deny that would be unescapable), toolguard emits an additionalContext "UNMEASURED" marker, stop emits `{"decision":"block"}` bounded by `stop_hook_active` exactly like harness_core::gate::run's panic barrier (empty stdin = manual run exits 1 with no fabricated decision), and statusline prints the explicit `unknown` band. The CLI/skill-consumed subcommands (note/metrics/ctx/usage/eval/…), whose empty stdout would be read as real data ("no notes", "nothing dropped"), now exit 1 like bin/evalkit. Only the pure-observability hooks (guard/rescue/restore/distill-bg — injected prose with no machine consumer) keep exit 0, and they still report on stderr; README.ja.md gains the classification table enumerating each one's downstream consumers, and src/main.rs's stale "on any error we exit 0 and stay silent" module docstring was corrected to match the code. New tests/launcher_missing_binary.rs pins all of it (plus that a PRESENT binary is still exec'd with args passed through). v0.5.16: cargo fmt --all reformatting only (fixes the 'build & commit plugin binaries' smoke workflow's `cargo fmt --all --check` gate, chronically red on main since 2026-07-21 per scripts/check-ci-red.py); no behavior change. Context-rot guard for Claude Code: detect, rescue, restore, distill, and CONTROL what loads into context (rule-based allow/deny gate + /ctx pin/drop/load + switchable carryover). Subscription-native (hooks + subagent + skill, no API key). v0.5.14: Stop hook now runs under harness-core's run_guarded panic barrier (fail-closed block on crash instead of silent allow).
Claude Code2 Skills