Commit Graph

353 Commits

Author SHA1 Message Date
Peter Steinberger
87d412d557 fix(cron): keep scheduler state and quarantine in SQLite (#117071) 2026-07-31 15:47:06 -07:00
Omar Shahine
944cf08f94 docs(automation): rename scheduled-tasks feature wording to Automations (#114855)
* docs(automation): rename scheduled-tasks feature wording to Automations

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WhJ8EiMXue6ADLmHfb7FL6

* docs: regenerate docs map and add Automations glossary entries

* docs(templates): follow renamed automations-vs-heartbeat anchor

* docs(automation): fix markdown formatting drift

* docs(automation): teach the canonical automations tool and sync the copied heartbeat default

Review follow-ups: normal instructions use the automations tool with cron as
an explicit compatibility alias; every verbatim copy of the default heartbeat
prompt matches the new shipped text from the strings PR.

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 07:21:56 -07:00
joshavant
1237c0cf81 docs(hooks): document validation responses 2026-07-30 02:59:06 -05:00
joshavant
54a6dba0d3 fix(gateway): validate hook delivery accounts 2026-07-30 02:59:06 -05:00
harish ganeshmurthy
5496cff965 feat(cron): include run time in failure alerts (#80246)
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: haishmg <4529977+haishmg@users.noreply.github.com>
2026-07-30 12:25:10 +08:00
Vincent Koc
3f918d4b3c fix(hooks): honor user timezone in session memory (#116136) 2026-07-30 09:04:52 +08:00
Vincent Koc
9e041cd386 fix(hooks): preserve multi-account agent delivery (#116095)
* fix(hooks): preserve account routing for agent delivery

Refs #43866

Co-authored-by: Paul Desmond Parker <paul.parker@dcconnect.cn>

* test(gateway): prove hook account delivery handoff

---------

Co-authored-by: Paul Desmond Parker <paul.parker@dcconnect.cn>
2026-07-30 07:10:21 +08:00
salvormallow
73b5e7aab4 fix(hooks): save memory on automatic session rollover (#61675)
* fix(hooks): persist memory on session rollover

Co-authored-by: salvormallow <15044561+salvormallow@users.noreply.github.com>

* fix(hooks): persist memory on automatic session reset

* fix(hooks): keep auto-reset reason internal

* fix(hooks): retain auto-reset memory admission

* fix(hooks): make session rollover return explicit

* test(hooks): track session memory temp dirs

* fix(hooks): satisfy session memory return contract

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-30 04:13:26 +08:00
Peter Steinberger
ca07207649 docs(security): add safe Gmail reader setup (#116041)
* docs(security): add safe Gmail reader setup

* docs: leave release notes to release flow

* docs: refresh documentation map
2026-07-29 15:07:35 -04:00
Ryan Hughes
9560e17185 feat(hooks): add persistent hook session mode (#75918)
* feat(hooks): add explicit persistent sessions

* fix(hooks): validate persistent mapping session keys

* chore: leave persistent hooks note to release process

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-30 02:57:28 +08:00
RogueL90
499d48edbb cron: reject webhook URLs with embedded credentials (#51822)
* cron: reject webhook URLs with embedded credentials

* fix(cron): reject credential-bearing webhook URLs

* chore: leave cron webhook note to release process

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-30 02:32:32 +08:00
Sascha Kuhlmann
814b9f6e36 fix(hooks): bound agent runner admission (#104712)
* fix(hooks): gate agent admission on runner entry

Co-authored-by: Sascha Kuhlmann <117685070+coolmanns@users.noreply.github.com>

* fix(hooks): bound agent runner admission

Co-authored-by: Sascha Kuhlmann <117685070+coolmanns@users.noreply.github.com>

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-30 01:01:46 +08:00
Sascha Kuhlmann
819961a292 fix(hooks): avoid implicit hook delivery targets (#100486)
* fix(gateway): bind hook delivery before scheduling

Co-authored-by: Sascha Kuhlmann <117685070+coolmanns@users.noreply.github.com>

* test(cli): make stderr tail fixture deterministic

* test(cli): allow loaded runners to start

* fix(gateway): narrow hook delivery binding

Co-authored-by: Sascha Kuhlmann <117685070+coolmanns@users.noreply.github.com>

* fix(gateway): keep hook delivery normalization internal

* style(gateway): format hook delivery helper

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-29 23:14:46 +08:00
Vincent Koc
80707db7ab fix(plugins): bound hook execution and retire stale registrations (#115695)
* fix(plugins): bound hooks and own legacy registrations

* docs(hooks): clarify internal handler ownership

* fix(cli): retain message hook shutdown deadline
2026-07-29 16:44:05 +08:00
Peter Steinberger
669db2968f refactor(agents): retire TOOLS.md into an AGENTS.md section with a doctor migration (#113966)
* fix(agents): stop retired attestation hashes from faking a vanished workspace

* feat(agents): migrate TOOLS.md content into the AGENTS.md tools section

* refactor(agents): drop TOOLS.md from the workspace bootstrap set

* refactor(policy): read tool policy entries from AGENTS.md

* docs: describe local tool notes as an AGENTS.md section

* test(codex): drop TOOLS.md developer-instruction coverage with the removed path

* test(agents): cover the TOOLS.md doctor migration behaviors

* refactor(doctor): satisfy TOOLS.md migration lint

* test(agents): split workspace attestation survival coverage

* refactor(codex): simplify workspace context basenames

* refactor(doctor): keep TOOLS.md migration helpers module-local

* docs: regenerate docs map

* fix(doctor): keep migration claims fresh

* fix(doctor): preserve nested tool notes

* refactor(doctor): split tools migration helpers

* refactor(doctor): limit TOOLS.md migration to workspace root

* style(doctor): keep migration under line limit

* fix(doctor): recover interrupted AGENTS publish

* docs(hooks): describe root-only TOOLS.md migration accurately

* fix(doctor): preserve migrated tool guidance visibility

* test(agents): regenerate prompt snapshots after rebase

* fix(policy): block evaluation while TOOLS.md is unmigrated

* fix(doctor): check merged bootstrap budget per agent

* fix(doctor): keep budget helper internal

* refactor(doctor): keep migration budget helpers to their consumers
2026-07-27 03:56:30 -04:00
Peter Steinberger
b5137604ef feat(cron): default agent turns to the current conversation, add /loop, tighten cron tool surface (#114328)
* feat(cron): bind agent turns to current sessions

* feat(commands): add loop chat command

* test(cron): cover session defaults and loop commands

* docs(cron): document current defaults and loops

* fix(commands): scope /loop status and stop by conversation name tag

* fix(commands): widen /loop conversation tag to 48 bits

* fix(commands): include disabled jobs in /loop status and stop

* docs(cron): regenerate docs map

* test(cron): split session-target default tests to satisfy max-lines
2026-07-27 01:44:38 -04:00
Peter Steinberger
e935a008f8 docs(cli): cross-link agent exec from automation and policy pages (#114034) 2026-07-26 01:19:11 -04:00
Peter Steinberger
1e20cc814e docs: retire config keys that strict validation rejects (#113956)
* docs: correct retired cron/audit config keys, cron failure-alert default, memory recall default, and tool-search telemetry claims

- configuration-reference: cron block documented cron.webhook and cron.failureDestination, both retired by the config-surface reduction tranches (58452de711, edecdbd05e); the cron schema is strict so a copied snippet is rejected. Document only the live keys and note the doctor --fix migrations.
- configuration-reference: root-level audit block is retired; canonical path is logging.audit (src/config/zod-schema.root-shape.ts).
- configuration-reference: cron.failureAlert.after default is 2, not 3 (src/cron/service/failure-alerts.ts).
- memory-config: rememberAcrossConversations defaults on for personal installs (packages/memory-host-sdk/src/host/config-utils.ts), matching the canonical table earlier in the page.
- tool-search: telemetry records catalogSize, per-source counts, and search/describe/call counts, and only on tool_search_code results. No byte accounting exists in the runtime.

* docs: retire remaining references to removed cron, audit, and logging config keys

Sweep follow-up to the previous commit, covering the same bug class in the pages that still contradicted it.

- cron-jobs/cli-cron: global cron.failureDestination is retired; the destination fields now live on cron.failureAlert (src/config/zod-schema.root-shape.ts, merged by legacy-config-migrations.runtime.retired.ts:379). Per-job delivery.failureDestination bullets left intact.
- gateway/audit, cli/audit, gateway/protocol: root-level audit.* is retired; canonical path is logging.audit.*.
- logging: logging.redactSensitive is retired (dead-config-keys.test.ts:198; removed by legacy-config-migrations.runtime.tier-eval.ts:12). resolveConfigRedaction hardcodes DEFAULT_REDACT_MODE = tools, so redaction is unconditional. Also documented that redactPatterns replaces the defaults on the log path (redact.ts:419) while tool payloads always merge them.
- logging: consoleStyle accepts only pretty|json (zod-schema.root-shape.ts:106); compact remains the automatic non-TTY rendering style (logging/console.ts:40) but is no longer settable, and doctor maps a stored one to pretty.
- security: security --fix no longer touches redaction and the logging.redact_off audit check is retired (src/security/audit-loopback-logging.test.ts asserts it never fires).

* chore(docs): regenerate docs map after retired-key cleanup
2026-07-25 18:24:02 -07:00
Peter Steinberger
d1b534d7fa docs(heartbeat): align retired config options with fixed runtime policies (#113455)
The runtime retirement already shipped: busy deferral is automatic,
reasoning payloads stay internal, the HEARTBEAT_OK ack budget is fixed at
300 chars, the Heartbeats prompt section follows cadence, and tool-error
warnings are always on. Docs still advertised skipWhenBusy, ackMaxChars,
includeReasoning, includeSystemPromptSection, and suppressToolErrorWarnings
as live options; this aligns seven pages with the fixed policies and the
strict heartbeat field list, locks the claw-profile skipWhenBusy rejection
diagnostic with a dedicated test, renames includeReasoning-era test/comments,
and canonicalizes claw add-plan workspace path assertions (macOS realpath).
2026-07-25 06:52:27 -07:00
Peter Steinberger
a2acc8a755 fix(ui): keep subagent details in task panel (#113671) 2026-07-25 06:13:06 -07:00
Peter Steinberger
f43fac21c7 fix(gateway): stop showing retired HEARTBEAT.md in the agent files editor (#113621)
* fix(gateway): drop retired HEARTBEAT.md from agent core files

* fix(ci): stop asserting retired HEARTBEAT.md in docker release smoke

* docs: align HEARTBEAT.md references with cron scratch

* docs(agents): drop retired HEARTBEAT.md from workspace read comment
2026-07-25 04:58:31 -07:00
Alex Markson
d998a1db84 fix: SQLite WAL file can stay inflated on a running gateway until restart (#112951)
* fix: SQLite WAL file can stay inflated on a running gateway until restart

Since #82366 switched the periodic 30-minute checkpoint to PASSIVE (to keep
WAL maintenance off the event loop), no checkpoint on a running process
truncates the WAL *file* any more -- only close() does, i.e. a restart.
wal_autocheckpoint recycles WAL space in place but never shrinks the file,
and is itself a PASSIVE checkpoint a reader can transiently block. So when a
reader briefly pins frames (e.g. a memory reindex, a backup, a slow query),
the WAL grows past the autocheckpoint size and then stays parked at that
high-water mark for the whole life of the process. Observed in production: a
1.6 GB agent DB left a 1.6 GB -wal that only manual TRUNCATE checkpoints
could reclaim. This affects every SQLite-backed store (task registry, plugin
state, proxy capture, memory host, ...), not just memory.

Set PRAGMA journal_size_limit (default 64 MiB, overridable via
journalSizeLimitBytes) right after wal_autocheckpoint so any completing
checkpoint -- including the PASSIVE periodic/auto ones #82366 now relies on
-- truncates the WAL file back to the ceiling. This restores the bounded
on-disk WAL that TRUNCATE used to give, without reintroducing the blocking
checkpoint #82366 removed: journal_size_limit only changes how far a
completing checkpoint truncates, never checkpoint timing. The 64 MiB ceiling
sits ~16x above the autocheckpoint steady state (~4 MB at 1000 pages), so it
is inert in normal operation and engages only on pathological growth.

Related: #82366, #81715

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: tighten SQLite WAL ceiling proof

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 03:52:33 -07:00
Peter Steinberger
1e9d918037 feat(sdk): always persist media facts and ship facts-first replacements for legacy Media* surfaces (#113355)
* feat(sdk): always persist media facts and ship facts-first replacements for legacy Media* surfaces

PR 1 of the media legacy retirement program (audit-frozen, 4 PRs).

- Every media-bearing user turn now persists normalized __openclaw.media
  facts unconditionally while continuing to emit the legacy top-level
  Media* projection byte-identically (dual-write bridge; the conditional
  shouldPersistStructuredMediaEntries gate now always includes media).
- New replacement APIs, shipped before any removal: typed hook media
  facts (media[], originalMedia[], mediaStagingPending) on message
  events; {{AttachmentPath}}/{{AttachmentUrl}}/{{AttachmentContentType}}/
  {{AttachmentDir}}/{{AttachmentIndex}} template variables; focused
  openclaw/plugin-sdk/media-local-roots subpath split out of the
  deprecated agent-media-payload facade.
- Every legacy surface carries @deprecated naming its replacement, under
  one named compatibility record media-legacy-projection with the
  operator-approved removeAfter 2026-10-01 (two release trains; deletion
  additionally gates on a clean published-plugin artifact sweep).
- Generic transcript append invariant documented; SDK migration, hooks,
  and configuration docs updated to the facts-first path.

Writer golden matrix proves legacy bytes and model prompt bytes are
unchanged while nested facts become unconditional. 2,189 broad media
tests green; SDK api-baseline regenerated on fresh-env Testbox.

* feat(sdk): register media-local-roots subpath exports and deprecation metadata

Completes PR 1: package export map for openclaw/plugin-sdk/media-local-roots
plus the deprecated-subpath inventory and doc metadata entries for the
media-legacy-projection record.

* chore(sdk): track media-local-roots entrypoint and deprecated-export budgets

* fix(sdk): keep deprecated MSTeams buildMediaPayload re-export through the compat window

Deleting shipped runtime-api re-exports belongs to retirement PR 4 after
the media-legacy-projection window; PR 1 only deprecates. Also formats
the migration-guide schedule table.

* docs: regenerate docs map for media migration additions
2026-07-24 10:42:17 -07:00
Peter Steinberger
b23c7bd0f8 feat(cron): convert heartbeat tasks: entries into independent cron jobs (#113165)
Each legacy heartbeat tasks: entry becomes an editable system-created cron
job (declaration key heartbeat-task:<agentId>:<hash>, per-occurrence
identity for duplicate names) that fires a guarded heartbeat wake carrying
the task prompt plus current monitor scratch context. Task cadence is now
independent of the base heartbeat interval; active-hours, busy-retry,
min-spacing, and flood guards are preserved, deferred payload-carrying
wakes are retained and retried after the spacing floor, and colliding
task/event wakes cannot starve each other.

openclaw doctor --fix migrates existing blocks: async parse/plan, then one
synchronous SQLite transaction that rereads the pinned scratch revision,
upserts job rows, and strips the tasks: block atomically — concurrent
doctors serialize on the database and a losing run aborts untouched.
Orphan fields, invalid intervals, and incomplete entries block migration
of their block with a clear finding instead of silent text loss. The
runtime tasks: parser is deleted; leftover text is ordinary scratch prose.

Nine Codex gpt-5.6-sol xhigh autoreview cycles; final verdict clean.
2026-07-23 16:13:08 -07:00
Peter Steinberger
95b86a3b2b refactor(heartbeat): make cron monitor rows own heartbeat cadence (#113135)
* refactor(heartbeat): make cron monitor rows own heartbeat cadence

agents.*.heartbeat.every stays the documented desired-state input; gateway
reconciliation and openclaw doctor --fix write it through into durable
system-owned cron monitor rows, and a scheduled monitor tick carries its
persisted everyMs/anchorMs as the authoritative cadence, which the runner
adopts for subsequent event cooldowns. Doctor gains a read-only cadence
preview (resolves the scheduler seed without creating device identity) and
an idempotent fix path that converges monitor rows per agent.

The cron-disabled fallback timer is deleted per its named removal plan
(#110950): gateways with cron.enabled=false or OPENCLAW_SKIP_CRON=1 log a
startup warning and get no scheduled heartbeats; manual and event-driven
wakes remain.

* fix(ci): drop unused requestHeartbeat import and refresh plugin SDK baseline
2026-07-23 12:56:54 -07:00
Peter Steinberger
3e2b3ea4d5 feat(cron): database-backed heartbeat monitor scratch replaces HEARTBEAT.md (#112967)
* feat(cron): move heartbeat context into database-backed per-job cron scratch

- new additive cron_job_scratch SQLite table (revision tombstones keep
  compare-and-swap monotonic across unset/recreate; 256KiB cap)
- heartbeat runner reads monitor scratch instead of workspace HEARTBEAT.md;
  heartbeat_respond gains a private scratch replacement parameter
- openclaw doctor --fix migrates HEARTBEAT.md into scratch (hash-verified,
  archived under state backups, idempotent, symlink-contained)
- gateway cron.scratch.get/set admin RPCs + openclaw cron scratch CLI
- workspace bootstrap no longer seeds HEARTBEAT.md; Codex heartbeat file
  guidance removed; docs and prompt snapshots updated

* fix(cron): review round 2 — shared-workspace heartbeat migration and non-default agent monitors

- doctor migration groups agents by heartbeat source file and imports into
  every monitor before archiving/removing the shared file once
- exempt heartbeat payloads from the main-session default-agent restriction:
  monitors only poke the wake bus, so non-default agents converge again
- document why disabled monitors retain their last cadence (config default
  already resolves before the fallback)

* fix(cron): honor configured cron store, legacy heartbeat fallback, and safer doctor claim

* fix(cron): claim HEARTBEAT.md before committing scratch and restore without clobbering

* fix(cron): pin migration CAS to precondition revision, re-verify claim on release, archive first, report scratch as pending

* docs(heartbeat): remove retired config options

* fix(cron): crash-recoverable migration claims, partial-import rollback, latest-response scratch pairing

* test(heartbeat): keep latest scratch proposal paired

* fix(cron): roll back committed scratch on changed-claim release and restore no-row state

* fix(cron): revision-guarded rollback delete and recreated-file detection on claim release

* fix(cron): treat every failed claim re-verification as a migration conflict

* test(heartbeat): rename ack test after ackMaxChars retirement

* fix(heartbeat): keep monitor scratch out of bypass-scope runs

* fix(cron): resolve claimed symlinks on release and gate legacy fallback on proven scratch state

* fix(cron): strict claim-name recovery and per-entry migration grouping

* fix(ci): heartbeat scratch gate repairs — lint causes, dead exports, since-train, inventory path, prompt snapshot, regenerated docs map, SDK baseline, protocol bindings

* fix(cron): live-owner claim guard and canonical entry-key migration grouping

* fix(cron): archive claimed inode on release and flag orphan claims beside recreated files

* docs(cron): document process-global state-db invariant for scratch service ops

* chore(i18n): refresh native inventory line numbers after protocol binding regen
2026-07-23 11:10:49 -07:00
Peter Steinberger
4e9ae9fbff feat(cron): system-owned heartbeat monitor jobs replace the dedicated interval scheduler (#112585)
* feat(cron): system-owned heartbeat monitor jobs replace the interval scheduler

- new internal cron payload kind {kind:"heartbeat"}: execution pokes
  requestHeartbeat({source:"interval"}); reported in the protocol job
  schema, not accepted from client create/patch
- gateway converges one declaration-keyed monitor job per heartbeat-enabled
  agent (schedule every+deterministic phase anchor) at startup and on
  config reload; removes monitors for unconfigured agents
- heartbeat runner loses its interval setTimeout machinery; nextDueMs
  stays as the cooldown gate, event wakes unchanged

* test(cron): heartbeat monitor regressions; docs for cron-owned cadence

- converge/prune/failure-containment tests for heartbeat monitor jobs
- heartbeat payload run fires an interval wake, no system event
- scheduler tests converted from timer self-fire to wake-queue pokes;
  timer-mechanics-only tests deleted with the timer
- persisted-shape accepts the heartbeat payload kind
- docs: heartbeat cadence ownership + system payload kind

* fix(cron): heartbeat monitor review round 1

- targeted cron-monitor interval ticks use the full per-agent path so
  due-commitment sessions still deliver
- cron-disabled gateways keep a local fallback interval timer (shipped
  cron.enabled=false contract; removed when heartbeat config folds into
  cron in #110950)
- heartbeat job reconciliations serialize with latest-wins epochs and a
  bounded 30s retry after a failed convergence pass

* fix(cron): chain clamped fallback heartbeat timers past the setTimeout cap

* fix(cron): heartbeat monitor review round 3

- targeted monitor redirect skips wakes carrying heartbeat overrides and
  surfaces the per-agent terminal skip reason instead of not-due
- cron-disabled fallback timer re-arms with a 1s floor after each firing
  so a dropped wake cannot end the chain
- heartbeat payloads are system-owned at the service boundary: add requires
  the gateway opt-in, patches to the kind are rejected

* fix(cron): heartbeat monitor review round 4 — full ownership enforcement

- prune only jobs proven to be monitors (prefix AND heartbeat payload)
- existing monitors reject every update patch; declarative upserts on the
  monitor key require the gateway opt-in even with a different payload

* fix(cron): complete heartbeat monitor ownership boundary

- converge scopes declarative matching to real monitors so a colliding
  user job with the same key is never adopted or overwritten
- monitor removal requires the gateway systemOwned opt-in; ad-hoc
  API/CLI deletion is rejected, reconciliation cleanup still prunes

* docs(cron): record intentional enrollment-snapshot semantics for monitor ticks

* fix(cron): repair heartbeat monitor CI gates
2026-07-22 14:03:29 -07:00
Josh Avant
3acc168c4f fix(cron): persist explicit scheduled tool authority (#112483)
* fix(cron): persist explicit scheduled tool authority

* test(cron): cover explicit scheduled authority

* fix(cron): preserve legacy authority on routine edits

* test(cron): add explicit authority e2e matrix

* test(cron): harden explicit authority live proof
2026-07-22 02:28:49 -05:00
Peter Steinberger
edecdbd05e refactor(config): config-surface reduction tranche 3 — product consolidations (review request) (#111527)
* refactor(config): consolidate media model lists

* refactor(config): unify memory configuration

* refactor(config): consolidate TTS ownership

* refactor(config): move typing policy to agents

* refactor(config): retire product-level config surfaces

* refactor(config): share scoped tool policy type

* chore(config): refresh generated baselines

* fix(config): honor agent typing overrides

* fix(config): migrate sibling config consumers

* refactor(infra): keep base64url decoder private

* fix(config): strip invalid legacy TTS values

* chore(config): refresh rebased baseline hash

* fix(doctor): route legacy messages.tts.realtime voice to talk during tts move

* refactor(config): polish final layout names

* refactor(config): freeze retired tuning defaults

* feat(config): add fast mode default symmetry

* refactor(config): key agent entries by id

* docs(config): update final layout reference

* test(config): cover final layout migrations

* chore(config): refresh final layout baselines

* fix(config): align final layout runtime readers

* fix(config): align remaining readers

* fix(config): stabilize final layout migrations

* fix(config): finalize config projection proof

* fix(config): address final layout review

* docs(release): preserve historical config names

* fix(config): complete keyed agent migration

* fix(config): close final migration gaps

* fix(config): finish full-branch review

* fix(config): complete runtime secret detection

* fix(config): close final review findings

* fix(config): finish canonical docs and heartbeat migration

* fix(config): integrate latest main after rebase

* refactor(env): isolate test-only controls

* refactor(env): isolate build and development controls

* refactor(env): collapse process identity indirection

* refactor(env): remove duplicate config and temp aliases

* docs(env): define the operator-facing allowlist

* ci(env): ratchet production variable count

* fix(env): remove stale provider helper import

* fix(env): make ratchet sorting explicit

* test(env): keep test seam in dead-code audit

* test(env): cover ratchet growth and boundary; document surface budgets

* docs(config): document tier-eval consolidations

* docs(config): clarify speech preference ownership

* test(memory): align retired tuning fixtures

* refactor(memory): freeze engine heuristics

* refactor(config): apply tier-eval tranche

* refactor(tts): move persona shaping to providers

* refactor(compaction): move prompt policy to providers

* test(config): align hookified prompt fixtures

* chore(deadcode): classify test-only exports

* chore(github): remove unused spawn helper

* chore(deadcode): classify queue diagnostics

* chore(deadcode): remove unused lane snapshot export

* chore(plugin-sdk): ratchet consolidated surface

* fix(config): integrate latest main after rebase
2026-07-21 20:28:43 -07:00
Peter Steinberger
98742bc2c7 feat(cron): stream schedule sources with durable source identity (#112387)
* feat(cron): stream schedule sources (supervised command stdout)

Add gated argv stream schedules with bounded line batching and trigger.streamBatch composition.

Reuse the gateway ProcessSupervisor for source ownership, deterministic teardown, capped restart backoff, and schedule-key guarded batch execution. Expose additive protocol, CLI, tool, UI, docs, and generated snapshot surfaces without storage DDL.

Contract: stream schedules are event-driven, require cron.triggers.enabled, reject command payloads, and retain at most one bounded pending batch.

* fix(cron): reject retired stream source epochs at run admission

Thread an invalidatable per-owner source-generation token (ownerNonce.generation)
through cron.run admission alongside the schedule key. A batch handed to cron.run
under one source epoch can wait behind another run while its owner is stopped; a
disable→re-enable or A→B→A edit leaves the schedule key unchanged, so the key
check alone would admit the retired epoch's batch. The token is persisted in
job.state on every lifecycle write and compared at every admission site plus the
executeJobCore guard, so a stale epoch's batch is skipped.

Also fix direct stream-job mutations recording the wrong lifecycle status when
global cron is off but triggers are on: extract resolveStreamStopReason so the
direct path reports the remediable cron-disabled state like reconcile does.

* fix(cron): close stream admission windows from round-10 review

- Persist the retired source generation before draining stop teardown, so a
  batch queued behind another cron run cannot gain admission during the up-to-10s
  in-flight-batch wait (server-cron routed stop path).
- Add streamSourceGeneration to the closed gateway response schema (excluded from
  the writable patch schema) so a running stream job passes strict result
  validation without letting callers spoof source identity.
- Close the mutation-epoch ABA: track an eviction epoch so a snapshotted absent-0
  is trusted as unchanged only when no LRU eviction happened during the await.

* refactor(cron): stream sources own a durable logical identity

Split the conflated restart-generation/admission token into two concepts:
a persisted streamSourceIdentity owned by cron store mutations (rotates on
enable/disable, source replacement, once-trigger auto-disable, and explicit
retirement; stable across supervised child restarts) and a watcher-local
process generation used only to fence stale child callbacks. Admission now
requires schedule key + identity together at every window, closing the
A-to-B-to-A and restart-flush races from review rounds 8-11.

Also: match-mode regexes now see raw source text (the [truncated] marker is
applied after matching), stop-timeout failures set the live restartExhausted
mirror so shutdown preserves the terminal diagnostic, and the watcher is
split into owner/output/registry modules under the max-lines budget.

* fix(cron): harden stream teardown and intake from round-4 review

An exit queued ahead of a requested stop no longer counts toward restart
exhaustion (the synchronous stop fence owns it), overlapping cron.stop and
stopAndDrain share one memoized shutdown drain instead of double-stopping
every owner, raw output intake is bounded at 4x the batch cap so normal
64 KiB pipe reads stop losing complete lines to OS chunk boundaries, and
persisted-shape quarantine coverage for unsafe match expressions is pinned.

* fix(cron): keep watcher-internal owner disposal from retiring live identity

Disposing an obsolete owner while a start replaces it is not a durable
removal; a retiring stop there rotated the live job's identity and stranded
the replacement behind the CAS ownership guard. Also align the docs with the
implemented match semantics: complete lines match on full text past the
batch cap, only intake-cut prefixes are unmatchable.

* fix(cron): make oversized-line matching independent of pipe chunking

Partial lines are retained up to the raw-intake bound rather than the
delivery cap, so a complete over-cap line matches identically whether it
arrives in one callback or several; only a line the intake bound itself cut
remains an unprovable prefix. Reconcile also contains schedule-replacement
stop failures per job, matching the other stop branches.

* fix(cron): bound assembled lines, drop stale payload override, barrier stopAll

- enforce the 4x raw-intake per-line cap while assembling split callbacks,
  so an oversized line stays an unprovable prefix regardless of chunking
- stop passing the watcher-cached payload as a cron.run override; the run
  snapshots the persisted payload under its admission lock
- stopAll waits for every owner stop to settle before surfacing failures
- split cron-stream-output interleaving tests into their own file (max-lines)

* fix(cron): address first full-CI round (lint, knip, schema test, unused param)

* chore(cron): refresh codex prompt snapshots for stream schedule schema

* fix(cron): keep the first clean line after an intake drop ending at a newline

* fix(cron): fence stream reconcile list snapshots against direct mutation routes

A cron.list snapshot captured across the reconcile await could be applied
after a direct add/update route already started the owner, stopping it as
removed and retiring its live identity. A mutation revision bumped at every
direct route start invalidates the stale snapshot; reconcile re-lists
(bounded) instead of applying it.

* style(cron): format stream owner imports

* fix(cron): discard severed stream prefixes at EOF

* fix(cron): retry failed stream shutdown drains

* fix(cron): honor stream stop fence after output drain

* chore(cron): refresh landing checks
2026-07-21 15:01:30 -07:00
Kate Stahnke
4400f4ca91 fix(cron): hint after disable about list filtering disabled jobs (#78139)
* fix(cron): hint after disable about list filtering disabled jobs by default

* fix(cron): use !params.enabled in disable-hint guard for oxlint compliance

* docs(cron): clarify disabled jobs in list output

* fix(cron): keep disable hint interactive

* test(cron): use exported store snapshot helper

* test(cron): create disable-list regression job via service

* docs(cron): defer list default contract wording

* test(cron): tighten disable list coverage

Co-authored-by: Kate Stahnke <35552+kate@users.noreply.github.com>

* docs(cron): document enabled-only list default

Co-authored-by: Kate Stahnke <35552+kate@users.noreply.github.com>

---------

Co-authored-by: Kate <35552+kate@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 12:04:15 -07:00
Peter Steinberger
c5254f13ee refactor(cli)!: remove automatic gateway→embedded fallback from openclaw agent (#112074)
A Gateway timeout or closed connection now fails the command with an
actionable stderr hint instead of silently re-running the whole turn
embedded under a fresh gateway-fallback-* session. The silent fallback
could double-execute side effects (the Gateway may still finish an
accepted turn), returned context-free answers to --session-key callers,
and ran with the CLI host's local config. --local remains the only
embedded execution path.

Also deletes the resultMetaOverrides plumbing (the fallback was its only
writer) and the fallback marker fields added in #111645.
2026-07-20 23:30:37 -07:00
Peter Steinberger
783a5d21cf refactor(config): purge numeric tuning knobs behind built-in defaults (#111382) 2026-07-19 07:35:45 -07:00
Peter Steinberger
4e7ef6223c fix(cron): keep paced schedules stable across force runs and edits (#111331)
* fix(cron): preserve cadence ownership

* fix(cron): satisfy maintenance lint
2026-07-19 02:26:28 -07:00
Peter Steinberger
68771ebdfe feat(cron): script payloads behind the trigger gate (#111112)
Run script payloads through the shared headless code-mode executor with payload-grade budgets and success-only trigger.state persistence.

Reuse cron delivery, wake, pacing, and dangerous trigger-gate contracts for notify, wake, and nextCheck results.
2026-07-18 19:24:12 -07:00
Peter Steinberger
d96a87e8e9 docs: document session automation contracts (#111095) 2026-07-18 18:10:14 -07:00
Peter Steinberger
556a2ee276 feat(cron): add per-job dynamic cadence (#110978)
Add optional per-job pacing bounds across the cron API, CLI, tool schema, public output, and SQLite job envelope, requiring at least one bound. Allow only the currently running paced job to record a one-shot next_check proposal and carry it through isolated-run completion.

After successful runs, clamp the proposal to the job bounds and persist an exact one-shot slot marker so maintenance preserves only that timestamp. Clear the marker on runs, edits, and schedule normalization; preserve existing no-proposal, skip, timeout, and error scheduling behavior.
2026-07-18 23:43:39 +01:00
Peter Steinberger
09963412d1 fix(exec): track background commands as tasks (#110468) 2026-07-18 08:51:23 +01:00
Peter Steinberger
a9f82837a1 feat: inspect background tasks across web and mobile (#109150)
* feat: add background task details across clients

* fix: refresh background task clients and translations

* fix: keep background task details fresh

* fix: ignore deleted background task details

* refactor: split background task rendering

* fix: use canonical background task ids

* refactor: extract background task view types

* fix(apps): regenerate task localizations

* fix(ios): remove unused task screen import

* fix(apps): refresh task localization inventory
2026-07-16 13:08:42 -07:00
Peter Steinberger
246cb48849 docs(cron): remove retired run-log settings 2026-07-13 11:41:27 -07:00
Peter Steinberger
6551786a31 docs: harden Gmail hook guidance 2026-07-12 22:42:48 -07:00
Peter Steinberger
3d9b912b88 feat: sidebar session state slot, worktree/automation badges, archive disables bound cron jobs (#104730)
* feat(gateway): flag sessions with attached automations and disable bound cron jobs on archive

Session rows now carry hasAutomation, derived from a lifecycle-owned index
over the cron service's in-memory jobs; cron events push refreshed rows so
badges stay live. sessions.patch { archived: true } disables enabled cron
jobs bound to the session (locked binding re-check, internal/operator-admin
callers only); restore intentionally does not re-enable them.

Refs #104700

* feat(ui): sidebar session state slot and worktree/automation badges

The run spinner moves into a leading state slot shared with the unread dot,
keeping the timestamp visible during runs; muted fork/clock badges sit after
the title (outside the trail/action overlap so pinned rows and touch devices
keep them). New strings localized via ui:i18n:sync (English fallback pending
a keyed translation run).

Refs #104700

* test(gateway): pin cron binding broadcast test to the event mechanism

The shard shares one process; session-store state from earlier tests can make
the row load return null, which legitimately produces a keyless refresh
payload. Row-field projection stays covered by session-utils and
session-automation-index tests.
2026-07-12 06:19:01 +01:00
Peter Steinberger
fa77fe10d5 chore: migrate active GPT-5.5 references to GPT-5.6 (#104452)
* chore(models): migrate active GPT-5.5 references

* test(workboard): expect GPT-5.6 Sol default

* chore: keep release notes in PR body

* test(models): align picker fixtures with Sol default

* test: update PDF default model expectation

* test(qa): migrate thinking smoke to Luna

* test(gateway): align mock catalog with Sol default

* ci: retrigger exact-head PR checks

* test(gateway): document default catalog invariant
2026-07-11 06:30:57 -07:00
SunnyShu
a6bdc8092b fix(session-memory): honor configured slug model (#97007)
* [AI] fix(session-memory): forward hook config model to LLM slug generator

When llmSlug is enabled with a model override in the session-memory hook
config, that model was ignored — slug generation always resolved the
agent default model via resolveDefaultModelForAgent.

Add an optional model parameter to generateSlugViaLLM and pass
hookConfig.model from the session-memory handler. When a hook model is
provided, only the model is forwarded (provider is omitted) so
runEmbeddedAgent's built-in resolveInitialEmbeddedRunModel chain handles
alias, provider-qualified ref, and bare-name resolution through a single
source of truth — avoiding the routing drift that blocked prior PRs.

Fixes #89551

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(session-memory): centralize slug model resolution

Honor the session-memory slug model override while keeping default, alias, and provider-qualified model selection in the embedded runner.

Co-authored-by: SunnyShu <shu.zongyu@xydigit.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 22:08:12 -07:00
Peter Steinberger
46692355c9 feat(ui): add a background tasks pane to chat panes (#104010)
* feat(ui): add background tasks rail to chat panes

* chore(i18n): sync control-ui locale bundles

* fix(ui): match gateway owner-key task scoping and hide tasks rail on narrow viewports

* chore(i18n): translate background tasks rail strings
2026-07-10 17:56:25 -07:00
JC
59e95fe3fd feat: support GPT-5.6 Ultra across OpenClaw and Codex runtimes (#98021)
* feat: support GPT-5.6 Ultra across agent runtimes

Co-authored-by: J Cai <anyech@gmail.com>

* fix: keep harness projections discovery-free

* fix(codex): mirror V2 native subagent tasks

* chore: refresh plugin SDK surface budgets

* test: expose Ultra wire effort proof

* test(cron): avoid hoisted mock initialization race

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 15:23:24 +01:00
Peter Steinberger
a6768d9de5 feat(cron): event triggers — polled condition-watcher scripts via code mode (#101195)
* feat(cron): add headless code-mode driver and trigger-script evaluator

Part A of cron event triggers: runCodeModeScriptHeadless runs a script
to completion (exec/settle/resume, no snapshots, no session), plus the
cron-facing evaluator with per-job tool catalog cache, semaphore, 16KB
state cap, and closed failure taxonomy.

* fix(cron): correct trigger-script bootstrap flags and cache narrowing

* feat(cron): add event triggers (polled condition-watcher scripts)

Part B: trigger field on cron jobs gated by cron.triggers.enabled;
timer evaluates the script each due tick, quiet ticks leave no run
history, fired runs append the script message to the payload; once
semantics, min-interval floor, SQLite columns, RPC/CLI/agent-tool
surfaces, and docs.

* fix(cron): propagate triggerEval through startup catch-up outcomes

* fix(cron): honor cron staggering on quiet trigger ticks; fix trigger test types

* fix(cron): reject with Error reason in trigger-script abort test

* fix(cron): regenerate protocol/docs/snapshot artifacts and break madge cycle for trigger types

CI fixes for #101195: trigger evaluator result types move to the cron
types leaf (madge cycle), cron tool schema inventory gains trigger,
Swift protocol bindings + docs map + Linux prompt snapshots regenerated.

* fix(cron): drop underscore-dangle names in trigger code sync assert

* fix(cron): adopt registerHeadlessToolSearchCatalog after tool-search symbol localization

Upstream #101831 made registerToolSearchCatalog module-private; fold the
headless ref-only catalog registration into one public seam.
2026-07-07 19:12:38 +01:00
Peter Steinberger
f623d81f52 feat(ui): show background tasks live in the web Control UI (#100789)
* feat(gateway): broadcast task ledger changes as task events

* feat(ui): add background Tasks page to Control UI

* fix(gateway): address tasks page review findings

* fix(ui): surface tasks.cancel refusals on the Tasks page

* fix(gateway): guard stale task observer disposal against replacement gateways

* chore: satisfy lint and docs-map gates for tasks page

* test(gateway): await async agent unsub in stale-dispose test
2026-07-06 14:36:33 +01:00
Masato Hoshino
e7ca90e3af fix(hooks): flag hook event names that no core trigger emits (#99456)
* fix(hooks): flag hook event names that no trigger site emits

* docs(hooks): clarify bare family subscriptions in unknown-event note

* fix(hooks): word unknown-event diagnostics around core-emitted keys

* fix(hooks): apply unknown-event advisory to legacy config handlers too
2026-07-06 01:30:13 -07:00
Peter Steinberger
3cf0d00d90 docs: align source contract wording (#100186) 2026-07-05 01:41:40 -04:00