578cefcc35
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 578cefcc35 |
v0.8.6: work-box → Mac headers.log sync (tsk-2026-05-27-023)
Closes the last gap in the rate-limit-diagnosis pipeline: anthropic-ratelimit-*
headers captured on the MobaXterm work-box now flow to the Mac memory daemon
(Tier 4 Hindsight + Tier 7 mem0) automatically.
- lib/headers-sync.sh: incremental, offset-tracked, idempotent push of
headers.log to ~/.cloverleaf/headers-<hostname>.jsonl on the Mac, riding the
existing authenticated SSH ControlMaster. No new auth; password never in
argv/env. No-op when nothing new; re-seed on local rotation/shrink. Fully
graceful (no target / closed master / transport error → warn + continue;
never crashes the session).
- /headers-sync on|off|status|target <alias>|now slash command + TAB-completion
+ /help. Config persisted to $LARRY_HOME/.env. Auto-sync fires on REPL exit.
- Security: headers.log carries only anthropic-* headers + status lines — NO
PHI per Vera audit V7; transport reused unchanged (not weakened).
Layered cleanly on top of Clover #8's v0.8.5 (
|
|||
| 4f1ea86051 |
v0.8.5: rate-limit backoff + actionable message, streaming single-send, ErrorPI CR fix, phi once-notice
Diagnose-don't-assume rate-limit cluster (Clover #8). The rate_limit_error on a work-box with 90% of the 5h Max quota free was a short-window BURST rail, not 5h exhaustion — tripped by a stream->non-stream double-send per turn with no backoff. - Rate-limit backoff honoring retry-after (else exp 2/4/8 cap 30) + actionable header-parsed message naming the tripped rail; headers.log now captures every 429 (was OAuth+unified-* only), tagged with retry-after + rail. - parse_stream_to_response detects a non-SSE JSON error body (429/overload) and returns a distinct code so agent_turn surfaces it WITH backoff instead of re-sending the whole prompt (single-send invariant). Auto LARRY_NO_STREAM=1 on MobaXterm/Cygwin/MSYS; explicit LARRY_NO_STREAM=0 still forces streaming on. - ErrorPI fix: strip_cr on err_type/err_msg in _humanize_api_error (a trailing CR broke the case match AND carriage-overprinted "API error"); err/warn/log now strip embedded CRs defensively. (v0.7.5 sweep missed the error-display path.) - phi tier-5 notice once-per-session via $LARRY_HOME/.phi-notice-shown SESSION_ID flag (old export flag died in the $(...) subshell -> per-turn nag). Same-pattern sweep fixed the identical subshell-flag bug in _auto_phi_b64_roundtrip. Deliverable: Deliverables/2026-05-27-cloverleaf-larry-v085-ratelimit-streaming-fixes.md Co-Authored-By: Clover (Claude Opus 4.7) <noreply@anthropic.com> |
|||
| 31ffae6f36 |
v0.8.4: installer/updater detects HTML-sign-in-page responses and fails loud
Hardens the installer + auto-updater against the Gitea private-repo trap (Clover #5 diagnosis): an unauthenticated raw-file read of a sign-in-gated Gitea returns the HTML Sign-In page at HTTP 200, which `curl -fsSL` treats as success — so the old code parsed HTML as VERSION/MANIFEST/larry.sh content and silently aborted (or overwrote real files with HTML). This stranded a work-box at v0.7.3 until the REQUIRE_SIGNIN_VIEW=false flip. - New lib/fetch-safe.sh: fetch_validate URL DEST KIND [MAX_TIME]. Detects the HTML-login trap (DOCTYPE/<html/"Sign In - Gitea"/<title>Sign In markers, or text/html Content-Type) and validates content shape per file type (semver VERSION, path-list MANIFEST, shebang larry.sh, non-HTML .sh). On failure: actionable error + non-zero, target file left untouched. - install-larry.sh (curl|bash bootstrap) and larry.sh self_update() each carry a byte-identical inline copy (both run before lib/ can be sourced). - Every remote-content fetch routed through the validator: install fetch(); agent fetch; sync_from_manifest MANIFEST + per-file; _fetch_with_fallback. - Optional LARRY_GITEA_TOKEN / GITEA_TOKEN env var adds Authorization: token <PAT> for authenticated fetch against private repos. Never hardcoded/logged. Documented in --help + MANUAL.md. Co-Authored-By: Clover (Claude Opus 4.7) <noreply@anthropic.com> |
|||
| d4c382dc6d |
v0.8.3: tab-completion trailing-space no longer breaks command dispatch
The slash-command completer (__larry_complete_slash) intentionally appends a trailing space after a unique match for arg-command ergonomics, but the main_loop dispatcher matched exact `case` globs — so a completed `/quit ` missed the `/quit)` arm and fell through to "unknown command". Latent since v0.6.6 (tab completion). Fixed by rtrimming the dispatch key once at the `case "$input"` boundary, which also transitively protects the sub-command dispatchers (/origin, /phi-auto, /phi-sidecar, /mouse) that consume the same $input via _slash_args. Interior `/load FILE` spacing is preserved. Added a shared rtrim() helper to lib/cygwin-safe.sh next to strip_cr. Co-Authored-By: Clover (Claude Opus 4.7) <noreply@anthropic.com> |
|||
| 60b8f0e1c8 |
v0.8.2: Presidio sidecar for free-text NER (tier-5) — closes V1
The only path that closes V1 (free-text PHI gap — the dominant real-world
failure mode per Vera). Opt-in install; larry runs in v0.8.1 mode on hosts
without Presidio (MobaXterm/Cygwin per Bryan's accepted tradeoff).
New files:
- lib/phi-presidio-sidecar.py — FastAPI service on 127.0.0.1:$LARRY_PHI_PORT
(default 41189). Presidio AnalyzerEngine + AnonymizerEngine over spaCy
en_core_web_sm + 3 HL7-specific custom recognizers (HL7_MRN, HL7_CARET_NAME,
HL7_PHONE_BARE). POST /redact and GET /health.
- lib/phi-sidecar.sh — lifecycle (start/stop/status/health/ensure). ensure
is idempotent; called backgrounded from main_loop so it never blocks the
first prompt. Honors LARRY_PHI_VENV.
- lib/phi-client.sh — bash client (phi_client_available / phi_redact_text /
phi_redact_entities). CR-safe; 5s timeout bounds tier-5 stall.
larry.sh:
- auto_detect_phi gains tier-5: after tiers 1-4, before status summary,
source phi-client.sh, run Presidio on a token-masked copy of the input,
tokenize each entity through hl7-sanitize.sh tokenize-value (category
presidio_<TYPE>) so token IDs stay stable. Honors confirm + strict modes.
Removed the v0.7.3 early-return that skipped past tier-5 when tiers 1-4
found nothing — pure prose now always reaches tier-5.
- Token-safe substitution: existing [[...]] tokens are pulled to sentinels,
tier-5 value is replaced, sentinels restored — prevents the token-within-
token corruption that naive literal-replace caused on already-tokenized
text. Acronym guard drops HL7/clinical jargon (SSN/MRN/DOB/ADT) Presidio
over-tags as ORGANIZATION.
- Graceful degradation: sidecar unreachable → tier-5 no-ops with a one-time
stderr warning. /phi-sidecar slash command + completion table.
install-larry.sh:
- Probes python3 3.9+; offers to create $LARRY_HOME/phi-venv and install
presidio + fastapi + uvicorn + en_core_web_sm. Skips silently (with a
v0.8.1-mode note) on Cygwin/MobaXterm without python3, and on
non-interactive pipe installs. Sets LARRY_PHI_VENV in the larry shim.
MANIFEST: three new lib files added for auto-sync.
Prototype validation (Bryan's Mac, Apple Silicon, Python 3.14):
cold start (en_core_web_sm): ~9s (vs ~82s if Presidio auto-grabs _lg;
we pin _sm for the REPL budget)
warm analyzer latency: P50 20.6ms / P95 22.7ms
end-to-end HTTP round-trip: ~57ms warm; ~150ms first-post-startup
All comfortably under the 200ms-per-turn budget.
MobaXterm verdict: v0.8.2 is Mac/Linux-only. MobaXterm stays on v0.8.1 +
nudges, per Bryan's explicit acceptance. install-larry.sh enforces this
by platform detection; larry.sh tier-5 silently no-ops when the sidecar
is absent (which IS the MobaXterm path — no code is platform-gated).
Verification: bash -n clean on larry.sh + all 3 new lib scripts; python3
ast.parse clean on the sidecar; end-to-end tier-5 tested live against the
sidecar (pure prose, rule-pack+tier-5 combined with no token corruption,
!nophi bypass); strict-mode fail-closed abort tested; CR-taint, path-block,
and base64 round-trip batteries re-run green.
Co-Authored-By: Clover (Claude Opus 4.7) <noreply@anthropic.com>
|
|||
| 9fc38e743d |
v0.8.1: tool-result content-shape gating + base64 round-trip + review gate
Three changes expanding PHI safety envelope on the tool-result surface. Closes V2 + V12 + V2-sub from Vera's audit. No behavior change for users not interacting with HL7-shaped data. - Tool-name allow-list dropped. The v0.7.3 tool-result auto-PHI gate ran only on read_file (.hl7|.txt), nc_msgs, hl7_field, hl7_diff. v0.8.1 runs _auto_phi_looks_like_hl7 on EVERY tool result. On hit → route through lib/hl7-sanitize.sh. On miss → pass through unchanged. Closes V2: bash_exec / ssh_exec / grep_files / read_file of any extension all get scanned when their output is HL7-shaped. False- positive cost is negligible (extra regex pass on non-HL7 has zero behavioral impact). - Base64-wrapped HL7 round-trip. New _auto_phi_b64_roundtrip helper. Detects candidate base64 runs (length >= 200, [A-Za-z0-9+/=] only, length divisible by 4 — NOT entropy-based per Pax §V2-sub: HL7's repetitive prefixes survive base64 with LOW entropy, so entropy is the wrong signal). Speculatively decodes each candidate; if decoded bytes look like HL7, routes through hl7-sanitize.sh and re-encodes back into the result. Catches ssh_pull_smat sampled mode's TSV format. Requires python3 (installed everywhere larry runs); skipped with a one-time stderr warning when unavailable. Server-side TSV encoding kept (binary-safe transport); client-side unwrap handles the safety concern, no remote refactor needed. - Operator review gate for bash_exec/ssh_exec/ssh_pull/ssh_pull_smat results. When the tool produced HL7-shaped output OR the result exceeds LARRY_TOOL_RESULT_REVIEW_THRESHOLD bytes (default 8192), Larry prompts [Y/n/i] before passing the result back to the model. 'i' opens the full output in $PAGER then re-prompts. Default Y (zero friction). N substitutes a refusal JSON so the model surfaces that something was withheld. Skipped when LARRY_AUTO_PHI=off (opt-out consistency) OR no TTY (headless scripts unaffected). Override with LARRY_TOOL_RESULT_REVIEW=always for paranoid mode. Closes V12. Proactive same-pattern sweep. Searched for other call sites where tool output bypasses content-shape gating: only the one in agent_turn. The v0.8.0-c strict-mode tool-result branch was updated in lockstep so it now triggers on the broader (content-only) eligibility. Verification: bash -n clean; b64 round-trip unit-tested with three cases (real-world HL7 base64 → decoded contains tokenized PHI not clear-text PHI; plain text → passthrough; non-HL7 b64 → passthrough, no false positive). Co-Authored-By: Clover (Claude Opus 4.7) <noreply@anthropic.com> |
|||
| 7434e6e8b8 |
v0.8.0: PHI safety quick-wins — path-block + /load HL7 routing + strict mode
Three independent zero-risk patches closing V3/V4/V5/V6/V11 gaps from
Vera's static PHI-leak audit. Implemented per Pax's mitigation
recommendations. No new deps, no behavior change for users not handling PHI.
- tool_read_file / tool_grep_files / tool_glob_files / tool_list_dir now
refuse paths under $LARRY_HOME/{log,sanitize,sessions} and
$LARRY_HOME/{.oauth.json,.env} with a structured JSON error the model
must surface. Block-list evaluates at call time; comparison runs against
both the literal and realpath-canonicalized form of both PATH and
$LARRY_HOME. Closes V4 + V6 + V11 (de-sanitization key, OAuth tokens,
PHI clear-text audit log). The proactive same-pattern sweep extended
the block from read_file alone to grep_files/glob_files/list_dir.
- /load <file> pre-routes HL7-shaped content through lib/hl7-sanitize.sh
(segment-aware tokenizer) BEFORE the user_input auto-PHI pass. Closes
V3 — smat dumps loaded via /load no longer rely on the lighter per-word
classifier.
- LARRY_AUTO_PHI=strict (fourth value alongside off/on/confirm) is the
fail-closed mode. Aborts the turn when sanitizer is missing or returns
empty on HL7-shaped content, or when tokenize-value fails. On the
tool-result surface (can't kill an in-flight tool_use), substitutes
the result with a refusal sentinel so raw HL7 NEVER reaches the model.
Existing off/on/confirm semantics unchanged. /phi-auto strict toggle,
/help text, and tests updated. Closes V5.
Refs:
Deliverables/2026-05-27-cloverleaf-larry-phi-leak-audit.md (Vera)
Deliverables/2026-05-27-cloverleaf-larry-phi-mitigation-research.md (Pax)
Verification: bash -n clean; path-block unit-tested with 13 cases including
symlink resolution (file and dir), ../ traversal, nonexistent paths, and
the empty-LARRY_HOME edge case — all pass.
Co-Authored-By: Clover (Claude Opus 4.7) <noreply@anthropic.com>
|
|||
| 9dd5821436 |
v0.7.5: OAuth CR-taint fix + mouse opt-in + CR-safety sweep
- Fix bash arithmetic crash on MobaXterm/Cygwin: $(date +%s) was returning CR-tainted values landing in $(( )) operands - Mouse mode off by default; opt in via LARRY_MOUSE=1 or /mouse on - Comprehensive CR-safety sweep across lib/*.sh and larry.sh — every command-substitution result, file read, and user input that feeds an arithmetic context, case dispatcher, or path/header is now CR-stripped at the source New shared helper lib/cygwin-safe.sh defines three primitives: coerce_int VAL [DEFAULT] — for arithmetic / integer-test operands strip_cr VAL — for case patterns, regex tests, paths, headers read_clean VAR [PROMPT] — read -r wrapper that strips CR pre-assign Hardened call sites (14 files, 60+ patch points): - larry.sh: status-line date/tput, 3 y/N approvals, auth menu, API key - lib/oauth.sh: cmd_login + cmd_refresh date+%s captures - lib/nc-engine.sh: 5 y/N action prompts + find|wc arithmetic - lib/nc-msgs.sh: parse_time_ms (4 date sites) + meta-TSV time + MSG_COUNT - lib/nc-regression.sh: tr|wc count + hl7-diff ?-fallback arithmetic - lib/nc-smat-diff.sh: A_COUNT/B_COUNT/DIFFS_TOTAL - lib/nc-insert-protocol.sh: every awk-emitted line number → head/tail math - lib/journal.sh: _next_seq wc -l arithmetic - lib/lessons.sh: _next_id/_count + 2 y/N prompts - lib/hl7-sanitize.sh: cmd_count + clear-table y/N - lib/ssh-helper.sh: 4 local+remote wc -c integer compares - lib/nc-find.sh, lib/nc-table.sh, lib/nc-document.sh, larry-rollback.sh Reproduces the exact error Bryan hit: bash: ...: arithmetic syntax error: invalid arithmetic operator (error token is "") lib/cygwin-safe.sh added to MANIFEST so it auto-syncs on next launch. Co-Authored-By: Clover (Claude Opus 4.7) <noreply@anthropic.com> |