Releases: Lifecycle-Innovations-Limited/claude-ops
Releases · Lifecycle-Innovations-Limited/claude-ops
claude-ops v2.17.0
Release v2.17.0. See CHANGELOG.md for details.
claude-ops v2.16.0
Release v2.16.0. See CHANGELOG.md for details.
claude-ops v2.15.0
Added
- Triage decision-log hook —
ops-pocket-triage.pynow records each triage decision (event type, confidence, reasoning) via/opt/pocket-mcp/pipeline/ops-pocket-decisions.pywhen present (try/except-guarded, no-op if absent), building an audit trail for downstream reporting.
Changed
ops-message-listener.shinput hardening — defense-in-depth on the dispatch path: env-var isolation forQUEUE_FILE(no shell interpolation), JSON load guarded by try/except + isinstance, per-message bounds (MAX_LEN=4000, sender ≤64), control-char stripping, and NUL-delimited dispatch output so newlines in message text can't smuggle extra dispatch lines. Merged on top of origin's existing stdin-piping fix; keeps the|| truecall-site resilience.
(Ports two patches that had been applied directly on the deploy box into the repo, so the live checkout can track main cleanly.)
claude-ops v2.14.1
Fixed
ops-pocket-notifywrapper resolves symlinks. Thebin/ops-pocket-notifybash wrapper computed the Python script path fromdirname "$0", which resolves relative to a PATH symlink's directory rather than the real file — so invoking it via a~/.local/binsymlink failed to find../scripts/ops-pocket-notify.py. Nowreadlink -fs itself first. Also syncspackage.json(had drifted to 2.13.0) to the plugin version.
claude-ops v2.14.0
Release v2.14.0. See CHANGELOG.md for details.
claude-ops v2.13.0
Added
- Config-driven pocket notifications (
ops-pocket-notify) — interactive setup of which events, which channels, when. Pocket components emit an event id; the newbin/ops-pocket-notifydispatcher decides routing frompreferences.json → pocket.notifications: per-event channels (telegram/email/whatsapp/slack via the existing senders + out-queue), plus a full per-event schedule — cooldown, quiet-hours, active-days, and severity escalation (high bypasses windows). New events are off by default./ops:ops-settings → Configure notificationswalks each event interactively (channels + schedule + dry-run test-send) and writes the prefs;docs/pocket-notifications.mddocuments the schema + event taxonomy. The executor emitsworker.spawned/worker.failed, and the env-broker's notify hook points at the dispatcher.--dry-run --jsonresolves routing without sending (used by setup + tests).
claude-ops v2.12.0
Added
- pocket-env-broker — peer-authenticated secrets broker for restricted pocket workers. Restricted background workers (which no longer inherit the orchestrator's secret env, per 2.11.9) can now request a specific allowlisted secret at runtime via the
pocket-env <VAR>client, instead of all-or-nothing. The broker (scripts/pocket-env-broker.py, runs as the privileged orchestrator user) listens on a unix socket, authenticates the caller with SO_PEERCRED (must be the worker uid), checks a default-deny allowlist (env-broker-policy.json), returns the value over the socket only (never to disk), and audits every grant/deny. Ships with the client, policy + systemd templates, docs, and tests; the pocket executor forwards the broker socket path + task/worker ids to workers. - Env-broker observability. The broker keeps a metrics snapshot (
env-broker-health.json: request/grant/deny/uid-rejection counters, recent denials,anomalyflag), exposespocket-env-broker --status [--json], and surfaces anEnv-brokerline in/ops:ops-statusthat raises a⚠anomaly on any uid rejection (a prompt-injection probing signal). - Env-broker push notifications (opt-in). Set
POCKET_ENV_BROKER_NOTIFY_CMD(+POCKET_ENV_BROKER_NOTIFY_COOLDOWN, default 300s) and the broker fires that command with an alert on uid rejections / not-allowed denials — rate-limited, best-effort, never blocking request handling. Wired to the operator's own chat it is a self-notification (outbound-comms-gate exempt).
claude-ops v2.11.9
Security
- Pocket executor: optional least-privilege worker isolation (
POCKET_WORKER_USER).ops-cron-pocket-executor.pycan now launch eachclaude --bgworker as a restricted unix user viasudo -n -H -u <user>instead of inheriting the executor user's full privileges, capping the blast radius of a prompt-injected or auto-promoted task. Opt-in: setPOCKET_WORKER_USER(and optionallyPOCKET_WORKER_CLAUDE_CONFIG_DIRto point the worker at a readable Claude config). Default unset = unchanged behaviour.--dangerously-skip-permissionsis retained (required for unattended--bgworkers) but is now bounded by the worker user's FS/network grants rather than running with the executor's full access.
claude-ops v2.11.8
Security
- Account-rotation config: stop tracking
config.json; readers prefer the gitignored override.rotate.mjsandkapture-claim-credits.mjsnow resolve the rotation config from$CLAUDE_PLUGIN_DATA_DIR/account-rotation-config.json(wheresetup-account.mjsalready writes real accounts), falling back to a local gitignoredconfig.jsonand then the shipped emptyconfig.example.json.config.jsonisgit rm --cached'd so real emails can never land in a tracked file (it was already in.gitignorebut remained tracked). No data was ever leaked to the remote — the committedconfig.jsonwas always the empty default; this closes the accidental-commit footgun.
claude-ops v2.11.7
Added
- WhatsApp bridge: Linux (systemd-user) install path.
scripts/install-whatsapp-bridge-linux.shclones lharries/whatsapp-mcp, applies the in-repo claude-ops patches (scripts/whatsapp/apply-patches.py), drops three systemd-user units (whatsapp-bridge.service,whatsapp-backfill.service,whatsapp-backfill.timer), and pairs via the bridge's pairing-code flow. Idempotent — re-running is safe and only applies missing patches. POST /api/backfillREST endpoint on the bridge (patch). Lets the claude-ops daemon, a 2h systemd timer, orcurltrigger a fresh history backfill without restarting the bridge. Returns{"success":true,"message":"backfill requested"}when connected; 503 otherwise.- Auto-backfill on
events.Connected(patch). Every reconnect firesrequestHistorySync5s after Connected — replaces the previous "manual backfill only" behaviour. Idempotent; whatsmeow dedups by message ID. - Cross-platform
whatsapp-bridgedaemon entry inscripts/daemon-services.default.jsonviascripts/lib/whatsapp-bridge-up.shwrapper that brancheslaunchctl(macOS) /systemctl --user(Linux). Replaces the previous launchctl-onlycommand. whatsapp-backfilldaemon entry (cron0 */2 * * *) — fallback trigger for hosts without the systemd timer.- Python MCP server (
whatsapp.py) LID/contact resolver (patch).get_sender_namenow resolves viawhatsmeow_contacts.full_name/push_name/business_nameandwhatsmeow_lid_mapfrom the bridge'swhatsapp.db, instead of relying on the macOS-onlycontactstable populated by Contacts.app. Group senders in@lidform now resolve to their real names on Linux.
Fixed
PairPhonesilent hang in lharries/whatsapp-mcp (patch). Two fixes per the upstream whatsmeow godoc: (Fix A)time.Sleep(3 * time.Second)betweenclient.Connect()andclient.PairPhone(...)so the noise handshake completes; (Fix B)context.WithTimeout(..., 3*time.Minute)onPairPhoneso an internal hang is recoverable instead of leaving the process zombied with no PairSuccess and no Timeout error.requestHistorySyncSIGSEGV (patch). whatsmeow'sBuildHistorySyncRequest(nil, count)panics because it dereferences.Chat/.ID/.Timestampon the nil first arg (send.go:572). Rewritten to openmessages.dbread-only, pick the 50 most-recently-active chats, and anchor against each chat's oldest stored message — also more efficient than a global request.
Changed
/ops-inboxmulti-channel scan is now a parallelWorkflowfan-out — the scan/classify phase spawns one read-only scanner agent per available channel concurrently (via theWorkflowtool), each returning structured classified results (NEEDS_REPLY / WAITING / HANDLED / FYI + thechatIdneeded to reply), then a synthesizer merges them into prioritized buckets. Wall-clock collapses from sum-of-channels to slowest-single-channel. Rule 6 is preserved end-to-end: scanners are explicitly read-only (never send/archive/mutate) and all reply drafting, approval, and sending stay in the main session under the one-draft→one-approval→one-send gate; channels are availability-detected first so no scanner is spawned for an unconfigured channel. Agent Teams and sequential scan are retained as documented fallbacks for older harnesses under the same constraints.