* fix(scripts): make clawlog default behavior match documented usage
Running scripts/clawlog.sh with no arguments was printing the usage help
instead of the documented default behavior (last 50 lines from the past 5
minutes). Remove the early no-args help branch so the defaults are used.
Also validate that options requiring a value (-n, -l, -c, -s, -o) actually
receive one, preventing an unbound-variable abort under set -u.
Fixes#104058
* fix(scripts): preserve dash-prefixed operands in clawlog and add regression tests
ClawSweeper review feedback on #104059 noted that the missing-value
guards introduced in the previous commit also rejected valid operands
beginning with a dash (e.g., search text '-failed' or an output file
named '-debug.log'). Narrow the guards so they only reject genuinely
missing operands, not dash-prefixed values.
Add focused regression coverage in test/scripts/clawlog.test.ts for:
- no-argument default behavior
- missing values for -n/-l/-c/-s/-o
- acceptance of dash-prefixed operands
- --help still printing usage
Related: #104058
* test(scripts): isolate clawlog command execution
* test(clawlog): use managed temp directories
---------
Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* feat(ui): cron automation-ideas gallery and Create & run now in quick-create
The cron page gains a curated automation-ideas gallery (six starter
automations that pre-fill the quick-create wizard with editable prompt,
name, schedule, and delivery presets); it stays expanded until the first
job exists, then collapses to a slim band. The quick-create wizard's
final step adds Create & run now, which chains cron.run (force) on the
job id returned by cron.add so a fresh automation shows output
immediately instead of waiting for its first scheduled tick.
Also hardens scripts/control-ui-i18n.ts against models wrapping JSON
replies in Markdown code fences.
Closes#104746
* chore(ui): regenerate locale bundles for cron suggestions strings
Generated via authenticated ui:i18n:sync (claude-sonnet-4-6) for the new
cron.suggestions/quickCreate keys; keeps the locale structural-alignment
gate green.
* fix(ui): deliver watchdog suggestion results via notify preset
Codex review: the night-watch idea promised alerts but pre-selected the
isolated preset, which maps to deliveryMode none, so results were never
delivered. Use notify and reword the prompt to an explicit one-line
verdict (renamed key so the locale pipeline retranslates).
* chore(ui): regenerate locale bundles for watchdog suggestion
* chore(ui): refresh raw-copy baseline after rebase
* refactor(sessions): migrate runtime storage to sqlite
* test(sessions): fix sqlite CI regressions
* test(sessions): align remaining sqlite fixtures
* fix(codex): require sqlite trajectory recorder
* test(sessions): align orphan recovery sqlite fixture
* test(sessions): align sqlite rebase fixtures
* fix(sessions): finish current-main integration of the sqlite flip
Resolve the whole-store SDK removal across its owner boundary: drop the
loadSessionStore re-export and the registry whole-store wrappers, wire
hasTrackedActiveSessionRun into gateway chat, complete the
preserveLockedHarnessIds cleanup contract, flip the codex thread-history
import to storePath targets, and port remaining main-side tests from
file-store helpers to session accessor reads.
* chore: drop committed pebbles log, revert plugin-inspector bump, refresh generated docs
Remove the 1.8k-line .pebbles/events.jsonl work log from the branch, restore
the plugin-inspector advisory lane to main's pinned 0.3.10 so the supply-chain
bump gets its own review, and regenerate docs_map, the plugin SDK API baseline,
and the export-surface ratchet for the merged tree.
* feat(sessions): keep archived transcripts by default with zstd cold storage
Codex-style retention: deleting or resetting a session archives its
transcript as a zstd-compressed JSONL artifact (plain when the runtime
lacks node:zlib zstd) and keeps it until the disk budget evicts oldest
first. resetArchiveRetention now governs both deleted and reset archives
and defaults to keep; maxDiskBytes defaults to 2gb so retention stays
bounded, with archives evicted before live sessions. The cron reaper
follows the same knob instead of deleting archives on its own timer.
* fix(state): converge agent DB migration lineages and bound database growth
Merge coherence: run both structure-gated legacy memory-schema repairs
(flip-lineage drop, main-lineage identity rebuild) before the flip
migration so pre-flip v1/v2 and pre-merge flip v1/v4 databases all
converge, and hoist foreign_keys=OFF outside the schema transaction
where the pragma was silently ignored and the v1 sessions rebuild
cascade-deleted session_entries.
Growth guards: fresh agent DBs enable auto_vacuum=INCREMENTAL, WAL
maintenance releases freed pages in bounded passes (never a blocking
full VACUUM), and doctor reports state/agent DB bloat from freelist
stats.
* fix(codex): resolve the store path for thread-history import via the SDK
The supervision catalog passed the legacy sessionFile locator to the
storePath-targeted transcript mirror; resolve the agent store path with
the session-store SDK helper instead of a runtime-object seam so test
fakes and headless callers need no extra surface. Drop the obsolete
missing-session-id preprocessing case: sessions rows are NOT NULL on
session_id and upsert repairs id-less patches at write time.
* fix(sessions): fail safe on malformed disk-budget config and doctor stat errors
A malformed explicit maxDiskBytes disables the budget instead of
falling back to the destructive 2gb default the user never chose, and
the doctor bloat check skips databases whose paths stat-fail instead of
aborting doctor.
* fix(sessions): complete sqlite conflict translations
* test(sqlite): align hardening checks with maintenance
* test(sessions): inspect compressed transcript archives
* fix(tests): await session seeds and drop unused helpers flagged by CI lint
The five unawaited writeSessionStoreSeed calls raced their SQLite seeds
against the assertions, failing compact shards; the bloat probe drops a
useless initializer and the merged tests drop now-unused helpers.
* test(sessions): type legacy proof events directly
* test(sessions): align hardening contracts
* perf(sessions): read usage transcript sizes from SQL aggregates
Usage/cost scans walked every session and materialized every transcript
event just to re-stringify it for a byte estimate — the #86718 stall
class reborn on the DB. readTranscriptStatsSync sums stored JSON bytes
in SQLite without loading a single row.
* fix(sessions): re-root foreign-root transcript paths onto the current sessions dir
Restored backups, moved OPENCLAW_STATE_DIR, and rehearsal copies carry
absolute sessionFile paths from the old root; the containment fallback
kept those foreign paths, so migration read (and would archive) files in
the original root and reported local copies missing. Re-root the
canonical agents/<id>/sessions suffix onto the current dir when the file
exists there; genuine cross-root layouts still fall through unchanged.
* test(agents): seed harness admission through sqlite
* fix(sqlite): close agent db on pragma setup failure
* fix(doctor): compact and retrofit incremental auto-vacuum after session import
The migration is the sanctioned offline window: post-import compact
reclaims import churn and applies auto_vacuum=INCREMENTAL to databases
created before the fresh-DB pragma existed, so runtime maintenance can
release pages in bounded passes on every install.
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* refactor(ui): move dreams page modules to agents/memory (verbatim)
* refactor(ui): sidebar IA cleanup: Activity to Settings, Dreams into Agents Memory tab, single MCP mutation owner, Usage icon
Folds the per-agent Dreams page into the Agents page as a Memory panel and
deletes the dreams route; moves the session-scoped Activity page out of the
sidebar into Settings > System next to Logs; removes the MCP enable/disable
toggle from Settings > MCP so the Plugins page is the single mutation surface
for config.mcp.servers; gives Usage a coins icon so it no longer collides
with Overview.
Closes#104590
* docs: update Control UI docs for Activity/Memory/MCP sidebar changes
* fix(scripts): fail control-ui i18n sync closed on new untranslated keys without provider auth
An unauthenticated ui:i18n:sync silently recorded English fallbacks, which the
shipped-fallback CI gate then rejects; post-merge translation is owned by the
control-ui-locale-refresh workflow. Sync now errors on new untranslated keys
without a provider (OPENCLAW_CONTROL_UI_I18N_AUTH_OPTIONAL=1 opts back in),
and the ui AGENTS guide documents the commit-en.ts-only contributor flow.
* chore(ui): translate new sidebar keys, refresh i18n baseline, localize Memory tab expectation
* test(e2e): live-model scenarios for node-hosted MCP tools and skills
Adds --live to the node-plugin pond E2E: three real Anthropic
(claude-sonnet-4-6) agent turns prove the model can (1) call a node-hosted
MCP tool with a proof token verified in the MCP server's call log, (2) use
a node-published skill from its context, and (3) disambiguate identically
named tools from two nodes via deterministic node-prefixed names. Requires
ANTHROPIC_API_KEY; mock mode unchanged.
* style: explicit sort compare in pond tool-id assertion
* feat: add metadata-only message audit events
* chore(protocol): restore generated swift models and config baseline after rebase
* fix(state): gate agent-db ownership check before schema version
* fix(cli): sync audit command description into the root-help catalog
* fix(audit): require destination proof before classifying outbound messages as direct
* refactor(audit): drop dead migration guard and add contract comments
* docs(gateway): add dedicated audit history page and cross-links
* test(e2e): enable direct-mode message audit in the telegram proof SUT config
* test(channels): expect declared conversationKind in durable delivery session context
* fix(audit): record the routing channel id for inbound rows from plugin channels
* fix(audit): match channel-prefixed delivery targets in the destination route gate
* fix(audit): validate explicit target kind against the destination route kind
* fix(audit): use the canonical target-prefix grammar in the destination route gate and fail closed on foreign migration tables
* fix(audit): normalize nested provider and kind target prefixes in the destination gate
* fix(audit): strip registered provider aliases and the direct kind prefix in the destination gate
* chore(docs): refresh config baseline after rebase
* improve(pr): trust origin/main-matching wrappers when the canonical checkout is parked elsewhere
* improve(crabbox): hint at lease expiry when reused-lease runs fail fast
* fix(pr): pin the wrapper trust anchor to the remote-tracking ref
* feat(tooling): extend strict-ratchet lane to all remaining leaf packages
* fix(packages): burn down indexed-access debt in ai and agent-core
All 196 noUncheckedIndexedAccess errors fixed behavior-identically
(iteration, .at()/slices, DataView byte math, guarded queue peeks) plus
cleanup finds: a sparse-tool diagnostic bug, deduplicated Responses
call/item ID parsing with an honest string|undefined splitter, and a
clearer local failure for redacted-thinking blocks missing signatures.
Removes all 17 remaining non-null assertions across ai, gateway-client,
and llm-core so the assertion ban aligns 1:1 with the ratchet lane.
speech-core joins memory-host-sdk as structurally deferred (imports
src/** via plugin-sdk path mappings).
* feat(tooling): add noUncheckedIndexedAccess strict-ratchet lane
* fix(packages): make indexed access explicit across ratchet packages
Burns down all 65 noUncheckedIndexedAccess errors in the seven ratchet
packages with behavior-identical restructuring (iteration, charAt/slice,
regex-group guards, validated hextet tuple). net-policy invariant
violations now throw instead of failing open. Adds
@openclaw/normalization-core/expect (expectDefined/first/last) with
subpath export and tests. memory-host-sdk fixes kept but the package
stays out of the lane: it re-exports core src/** so the flag would apply
transitively to all of core.
* fix(lint): keep .oxlintrc.json strict-JSON parseable for extension lint wrappers
* feat: node-hosted plugins — dynamic tools, MCP servers, and skills
Nodes become declarative plugin hosts:
- node.pluginTools.update: node hosts publish plugin-registered agent tool
descriptors; gateway materializes them as agent tools executing via
node.invoke under the node command allowlist, with tools.effective
invalidation and node online/offline removal.
- Trusted paired-node descriptors: no gateway-side plugin registration
required; gateway.nodes.pluginTools.enabled off-switch (default on);
description/count caps; deterministic node-prefixed collision names.
- Declarative node-hosted MCP: nodeHost.mcp.servers (McpServerConfig shape)
starts MCP clients on the node host, publishes tools as pluginId node-mcp,
executes via built-in mcp.tools.call.v1 with per-layer timeouts, failure
isolation, and orphan-safe shutdown. No re-pairing when servers change.
- Node-hosted skills: node.skills.update publishes ~/.openclaw/skills
content (64 skills/64KB/512KB caps both sides); gateway merges them into
the skills snapshot while connected and exec host=node is available, with
node:// locators, node-prefixed collisions, disabled command dispatch,
and gateway.nodes.skills.enabled + nodeHost.skills.enabled switches.
- Security: node-supplied pluginIds cannot satisfy pluginId-scoped tool
allowlists unless gateway-registered; reserved node-mcp id requires the
core MCP descriptor shape; protocol registry kept out of public
plugin-sdk dts.
- E2E: pond harness proves publication, MCP round-trip, skills locator, and
disconnect/reconnect for all three surfaces.
* style: format node-plugin-tools test
* fix(skills): keep status loader unfiltered when eligibility is passed
skills.status started passing eligibility for the node-skill merge, which
flipped loadWorkspaceSkillEntries into filtered mode and dropped disabled
skills from status reports (QA plugin-lifecycle-hot-reload timeout). Status
now merges node skills explicitly around an unfiltered load. Also: regen
docs_map for new node docs sections; add the intentional node-host MCP
onclose suppression to the lint-suppression allowlist.
* chore(lint): enforce no-floating-promises repo-wide
* feat(tooling): split DOM globals out of the Node-side typecheck program
tsconfig.core.json now compiles src/ + packages/ with lib ES2023; new
tsconfig.ui.json owns ui/ with DOM. Web-global names used by Node code
alias to canonical undici/stream-web types; highlight.js loads through a
validated narrow API because its d.ts force-includes lib.dom. Boundary,
sparse-guard, changed-lane routing, and profile lanes cover the new ui
graph.
* chore(deps): declare undici-types and teach knip about the highlight.js runtime require
* ci: retrigger dropped pull_request synchronize event
* refactor(types): derive web-global aliases from @types/node fetch globals, drop undici-types dep
* ci: retrigger after dependency guard cleared
* fix(scripts): add ui lane to changed-lanes declaration union
* chore(types): add declaration files for scripts/lib and scripts/e2e modules
* chore(types): add declaration files for top-level script modules (a-m)
* chore(types): add declaration files for top-level script modules (n-z)
* test: use a non-secret-shaped gateway token fixture
* test: type ci workflow guard helpers for the root test lane
* chore(tooling): typecheck root test/** with a dedicated tsgo lane
- test/tsconfig/tsconfig.test.root.json: root-test program (strict unused checks,
fixtures excluded; two Docker E2E clients that import built dist/** stay out,
same rationale as the scripts/e2e exclusion in tsconfig.scripts.json)
- tsgo:test:root wired into tsgo:test, check:test-types, scripts/check.mjs, and
the ci.yml test-types shard, mirroring the tsgo:scripts lane (#104348)
- changed-lane routing: test/**/*.ts (excluding fixtures) and the lane tsconfig
now trigger 'typecheck test root' in check:changed; previously test/ paths ran
lint only, so harness type errors surfaced first in CI (#104287 envDir case)
- burn down all 1071 latent type errors in the program: precise param/local
types across test/scripts, test/vitest, test/e2e, and transitive scripts/e2e
program members; 205 sibling .d.mts declaration files for imported .mjs
modules (committed separately); zero any, zero ts-expect-error
- resolve the pre-existing testing star-export ambiguity in
scripts/e2e/parallels/common.ts with an explicit re-export
Closes#104388
* chore(types): correct declaration fidelity per structured review
- re-derive 51 .d.mts files from implementation data flow instead of
initializers: fix a wrong never return (runTestProjectsDelegation returns
the child), add encoding-sensitive exec/spawn overloads (plain-gh), restore
the full release profile union, make parsed paths string | null, add missing
parseArgs fields via help/non-help unions, add a missing sibling declaration
(budget-number-args), drop 15 unused lint directives
- precise install-record/tuple typing removes the type-aware oxlint
regressions the first declarations caused in scripts/e2e implementations
- route .mts declaration edits under test/ to the testRoot lane and reference
the test-root project from tsconfig.projects.json so tsgo:all covers it
(closes both review findings against the lane wiring)
* chore(scripts): keep telegram runner dist typing structural for the boundary guard
* chore(types): declare runtime pack and gateway readiness exports added on main
* test: pin the importTargetPlan form of the plugin-contract plan import
The guard expectation still referenced the raw await import( form that
7ae5996bb3 (#103975) replaced with the importTargetPlan fallback helper;
the assertion fails on current main.