Commit Graph

510 Commits

Author SHA1 Message Date
Vincent Koc
adf78cefbd refactor(daemon): centralize environment source lookup (#113283) 2026-07-24 16:45:03 +08:00
RickLin
328fa5b964 fix(gateway): actively relaunch launchd restarts (#104637)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 08:58:18 -07:00
shawnduggan
f53e9f6e1c fix: allow macOS gateway restart while LaunchAgent owns its port (#89096)
* fix(daemon): allow launchd restart while gateway port is busy

* fix(daemon): verify launchd restart port ownership

* fix(macos): refresh launchd restart ownership guard

Protect the managed LaunchAgent PID, re-read after cleanup, and reject mixed or unattributed port ownership before service mutation.

Co-authored-by: Shawn Duggan <shawn.duggan@gmail.com>

* fix(macos): refresh launchd pid during stale cleanup

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 02:49:28 -07:00
Alix-007
3c10513c72 fix(doctor): bound legacy launchd cleanup (#109116)
* fix(doctor): bound legacy launchd cleanup

Bound both legacy launchctl cleanup attempts to five seconds while keeping the existing bootout-then-unload order. Only move the legacy plist after a successful command or an explicit already-unloaded result; leave it in place when timeout or another failure prevents confirmation so a later doctor run can retry. Report filesystem cleanup failures as skipped instead of claiming removal.

* fix(doctor): verify launchd cleanup state before moving plist

Poll a bounded launchctl print postcondition after legacy bootout and unload. Treat loaded, unknown, and timed-out probes as unconfirmed so doctor leaves the plist available for retry.

* test(doctor): clarify launchd cleanup postcondition

* fix(doctor): reject timed-out launchd probes

Preserve timeout evidence from the command runner, including sanitized timeout messages, so partial not-loaded output cannot authorize plist removal.

* fix(doctor): classify no-output launchd timeouts

* test(doctor): trim launchd cleanup cases

Co-authored-by: Alix-007 <li.long15@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-20 20:36:04 -07:00
Peter Steinberger
c45e3dd315 fix(gateway): avoid macOS startup freeze during worker reconciliation (#111533)
* fix(gateway): warm system CA before worker reconciliation

* fix(gateway): tolerate denied worker warmup
2026-07-19 14:39:25 -07:00
Peter Steinberger
359859d343 fix(gateway): keep first outbound TLS off the main event loop on macOS (system-CA/trustd) (#111473) 2026-07-19 09:01:09 -07:00
Peter Steinberger
fab3cdf1d8 refactor(gateway): simplify lifecycle mutation contracts (#110583)
* refactor(gateway): simplify lifecycle mutation contracts

* refactor(cli): unexport internal emitDaemonActionMessage
2026-07-18 11:09:21 +01:00
cxbAsDev
94e1cc9a4e fix(daemon): distinguish shared and embedded SQLite in system Node warning (#107990) 2026-07-18 10:02:28 +01:00
Peter Steinberger
6416baef83 fix(gateway): audit managed service starts (#110497)
* fix(gateway): audit managed service starts

* chore: drop changelog edit (release-only per repo policy)

* test(gateway): align start routing mocks
2026-07-18 08:26:45 +01:00
Peter Steinberger
8992f92dab feat(gateway): idempotent start, non-interactive stop guard, unified lifecycle audit (#110323)
* feat: guard gateway lifecycle mutations

* fix: harden gateway lifecycle mutation guards

* fix: harden gateway lifecycle audit safety

* fix(cli): repair gateway lifecycle checks

* fix(cli): satisfy lifecycle CI gates
2026-07-18 07:01:38 +01:00
MatthewSynthia
c23dc147b8 fix: launchd reload handoff strands gateway when restart races the drain window (#110213)
* fix(daemon): reload handoff outwaits gateway drain before re-bootstrapping

The launchd reload handoff waited only 15 x 0.2s (~3s) after bootout for the
label to unload, but the booted-out gateway keeps the label registered until
its drain-before-exit window (up to 300s) completes. Bootstrap then failed
with EIO mid-drain, and the kickstart -k fallback cannot succeed on a
booted-out label, leaving the LaunchAgent deregistered and the gateway down
until a manual bootstrap.

Extend the post-bootout wait to cover the full restart-deferral budget plus
margin (315 x 1s, derived from DEFAULT_RESTART_DEFERRAL_TIMEOUT_MS), and
replace the single dead kickstart fallback with a bootstrap retry loop that
only falls back to kickstart -k while the label is actually registered, so
the handoff never exits with the service deregistered.

Closes #110137

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(daemon): scale reload bootout wait to the effective drain budget

A config-raised gateway.reload.deferralTimeoutMs would outlast the fixed
default-derived wait and reopen the stranded-LaunchAgent race. Thread the
effective deferral timeout from restartLaunchAgent into the handoff and derive
the reload bootout wait from it; unbounded (<=0) configs keep the finite
default wait, with the bootstrap retry loop covering the overshoot.

Related: #110137

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(daemon): derive reload wait from launchd ExitTimeOut and keep failed bootstrap status

Review follow-up: the bootout SIGTERM path is bounded by the plist's
ExitTimeOut, not the gateway's restart-deferral config, so derive the reload
bootout wait from LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS plus margin and drop the
deferralTimeoutMs threading. Capture a failed bootstrap's status in the else
branch: after a completed if with a false condition $? is 0, so exhausted
retries logged 'restart done' and exit 0 while the LaunchAgent stayed
deregistered. Adds an execution-level retry-exhaustion test that runs the
generated script against an always-failing launchctl stub.

Related: #110137

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(daemon): exercise delayed launchd reload handoff

Run the generated reload handoff through delayed-stop and exhausted-bootstrap
paths, and clarify that the wait covers launchd's ExitTimeOut stop window.

Co-authored-by: MatthewSynthia <299972631+MatthewSynthia@users.noreply.github.com>

* test(daemon): narrow generated handoff script

Fail clearly when the spawn arguments omit the generated script and pass a
narrowed string to the execution helper.

Co-authored-by: MatthewSynthia <299972631+MatthewSynthia@users.noreply.github.com>

* fix(daemon): retry bootstrap after launchd kickstart race

Continue the bootstrap retry loop when a label disappears between the
registration check and kickstart, and cover the race by executing the generated
handoff script.

Co-authored-by: MatthewSynthia <299972631+MatthewSynthia@users.noreply.github.com>

* test(daemon): make handoff no-wait sentinel explicit

Co-authored-by: MatthewSynthia <299972631+MatthewSynthia@users.noreply.github.com>

---------

Co-authored-by: MatthewSynthia <299972631+MatthewSynthia@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 06:44:02 +01:00
Peter Steinberger
da69daeb72 feat(onboarding): recommend plugins and skills from installed apps (#109668)
* feat(onboarding): recommend plugins and skills from installed apps

Scan installed macOS apps during classic onboarding (TCC-free), gather
candidates from official catalogs + ClawHub search, let the configured
model pick genuine matches, and offer an opt-in multiselect install step.
Adds a device.apps node-host command (default-off sharing, Android-parity
envelope) so remote gateways can request a paired Mac's inventory, and a
wizard.appRecommendations kill switch. Custom setup-inference completions
no longer inherit the 32-token verification-probe output cap.

* feat(onboarding): recommend apps in guided flow

* fix(onboarding): harden app recommendations against ClawHub self-promotion

Third-party ClawHub skills are never pre-selected regardless of model tier
(publisher-controlled listing text reaches the matcher prompt and could
promote itself); their labels now say they install third-party code.
Installed-app scans follow symlinked .app bundles. Matcher output stays
bounded by the resolved model's own maxTokens budget (documented invariant).

* fix(onboarding): key official catalog candidates by resolved plugin id

Real catalog entries are package manifests without a top-level id; keying the
candidate map and channel/provider classification by entry.id collapsed the
whole official catalog into one undefined-keyed entry, so no official plugin
or channel was ever recommended. Regression test runs against the bundled
catalogs.

* fix(onboarding): satisfy lint, types, deadcode, and migration gates

Split the guided-onboarding test into a self-contained custodian suite to stay
under max-lines. Narrow app-recommendation exports (drop dead node-payload
normalizer, unexport internal types/helpers, route candidate tests through the
public API), replace map-spread with a helper, unexport device.apps result
types, add installedAppsSharing to node-host migration expectations, cast the
wizard multiselect mock, and regenerate the docs map.

* test(onboarding): register new live test in the shard classifier
2026-07-17 14:07:59 +01:00
Yiğit ERDOĞAN
e228a3ca3a fix: gateway.cmd launcher garbles non-ASCII profile paths on non-CJK Windows locales (#108967)
* fix(daemon): encode Windows cmd launcher to the console OEM code page

* fix(infra): unexport resolveWindowsSystemEncoding

The launcher encoder now resolves the boot-time OEM code page via
resolveWindowsOemEncoding, leaving resolveWindowsSystemEncoding with no
external importers; the dead-export ratchet (knip all-exports) fails CI
on exported-but-module-local functions.

* test(windows): cover OEM launcher encoding resolver

* fix(windows): declare launcher OEM code page

* fix(windows): fail closed on unsupported OEM pages

* fix(windows): reject CP1258 precomposition drift

* fix(windows): guard CP864 launcher syntax

* test(windows): pin OEM launcher code page

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-17 00:16:59 -07:00
xydt-tanshanshan
a3e526a9d0 fix(daemon): prevent gateway OOM crash loops under sustained load (#96250)
* [AI] fix(daemon): set default --max-old-space-size=8192 in gateway service env

Generate a managed NODE_OPTIONS with --max-old-space-size=8192 for the
gateway systemd service, discarding ambient host NODE_OPTIONS to prevent
--require/--inspect persistence.  8192 MB is chosen as a safe default
that prevents the common OOM crash-loop with the default Node ~4 GB heap
under sustained load.

Related to #96203

* fix(daemon): adapt gateway heap limit to host memory

* fix(daemon): keep gateway heap helpers internal

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 20:12:12 -07:00
pacoa
14dc557cee fix: use effective daemon port flag (#109294)
* fix: use effective daemon port flag

* fix(daemon): unify effective port parsing

Co-authored-by: pacoa <29181120+pacoa-kdbg@users.noreply.github.com>

* fix(daemon): skip consumed port values

Co-authored-by: pacoa <29181120+pacoa-kdbg@users.noreply.github.com>

* style(daemon): format effective port handling

Co-authored-by: pacoa <29181120+pacoa-kdbg@users.noreply.github.com>

---------

Co-authored-by: Paco Avelar <[email protected]>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 17:11:09 -07:00
Alix-007
8f1c6df748 fix(daemon): bound Node binary lookup (#109239)
* fix(daemon): bound Node binary lookup

* docs(changelog): note bounded daemon Node lookup

Co-authored-by: Alix-007 <li.long15@xydigit.com>

* docs(changelog): keep release notes out of contributor PR

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 12:32:08 -07:00
thomas.szbay
b06fe2a673 fix(kill-tree): verify process group leader before using group kill to prevent gateway SIGTERM (#76259) (#94697)
* fix(kill-tree): verify process group leader before group kill to prevent gateway SIGTERM (#76259)

- Add isProcessGroupLeader() to killProcessTree/signalProcessTree: ps -p <pid> -o pgid= primary check with /proc/<pid>/stat fallback on Linux. Group kill only when the PID is its own process group leader; non-leaders fall back to single-pid kill, preventing accidental gateway SIGTERM when a non-detached child shares the gateway's process group.
- Propagate detached: true to all detached-spawn cleanup callers (exec-termination, agent-bundle LSP, mcp-stdio, bash, supervisor pty, agent-core nodejs) so detached group cleanup survives leader exit.
- Gateway/daemon cleanup paths (schtasks, restart-health) keep the leader-checked default (detached omitted).

Closes #76259

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

* refactor(process): tighten process-group ownership checks

* refactor(daemon): split restart diagnostics

* refactor(daemon): isolate restart health types

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 12:30:51 -07:00
Shakker
244f4965dc feat: add external gateway supervision policy 2026-07-16 17:01:39 +01:00
Alix-007
2d0f0d0ec0 fix(daemon): bound Node runtime probes (#109127) 2026-07-16 09:00:06 -07:00
Abner Shang
5ad0d4d6c0 fix: avoid false restart failure during startup migrations (#105544)
* fix: wait for startup migrations on restart

* fix: honor restart readiness caller context

* fix: preserve restart service identity

* fix: refresh readiness context after repair

* fix: bound migration restart wait by wall clock

Co-authored-by: Abner Shang <abner.shang@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 02:04:49 -07:00
Peter Steinberger
8959ac8b17 refactor(windows): remove launcher encoding test seam (#108750)
* refactor(windows): remove launcher encoding test hook

* test(windows): widen launcher fixture buffer type
2026-07-16 01:13:21 -07:00
Jason
ccec0224fa fix(daemon): gateway fails to launch on Windows when the profile path contains CJK characters (#107751)
* fix(daemon): write Windows gateway launchers in encodings wscript/cmd can decode

gateway.vbs and gateway.cmd were written as UTF-8 without BOM, but
wscript.exe only reads .vbs as ANSI or UTF-16 LE with BOM and cmd.exe
reads .cmd in the console OEM code page, so installs under CJK profile
paths failed with "file not found" (#107416).

Write .vbs as UTF-16 LE with BOM, write non-ASCII .cmd content in the
system code page when it matches the console page (CJK/Thai locales),
and BOM-sniff plus code-page-fallback on read so launchers from older
installs keep parsing and migrate on refresh. The hidden .vbs launch
path originates from #95480, which addressed console visibility only.

* refactor(daemon): drop unused WindowsLauncherScriptFormat export

The type is only referenced by encodeWindowsLauncherScript's format
parameter within the module, so the export tripped check-deadcode-exports.
Keep it module-local.

* fix(daemon): mark code-page cmd launchers with their encoding for deterministic readback

Prepend an ASCII '@rem openclaw-launcher-encoding=<label>' line to code-page
.cmd launchers and decode by that marker instead of sniffing UTF-8. Some GBK
byte sequences are valid UTF-8 (隆 = C2 A1 reads as ¡), so the old sniff
silently corrupted readback and rejected valid paths; the marker makes decode
deterministic and drops the code-page probe (a PowerShell spawn) from the
frequent readScheduledTaskCommand poll path.

Also fix the representability guard for euc-kr: Node ICU decodes euc-kr as
KS X 1001 only, but Windows code page 949 is cp949/UHC, so the TextDecoder
cross-check false-rejected ~8,800 UHC extension syllables (똠 = 8C 63) that
iconv encodes and cmd.exe reads fine. Verify euc-kr via iconv's own cp949
round-trip; keep TextDecoder for the other five labels.

* fix(infra): write Windows restart helper scripts through the launcher encoder

The update-time restart helper wrote its temp .cmd as raw UTF-8 while
embedding the restart-log path, task name, and task script path, so a CJK
profile path or task name broke the same way as the gateway launchers
(#107416). Route the write through encodeWindowsLauncherScript: ASCII content
stays byte-identical UTF-8, CJK content gets the marked code-page encoding, and
an unrepresentable task name now fails the restart attempt cleanly instead of
writing a script cmd.exe would misread.

* chore(deps): minimize pnpm-lock delta for the iconv-lite promotion

Reset pnpm-lock.yaml to origin/main and re-add only the iconv-lite root
importer entry, dropping the unrelated @types/node peer-context flips and
audio-decode deprecation metadata that a mismatched-toolchain regeneration had
pulled in. The diff vs main is now the three-line importer entry only; the
version already resolves in main's tree via express -> body-parser/raw-body.

* refactor(windows): centralize launcher encoding

Co-authored-by: Jason Yao <wsyjh8@gmail.com>

* style(windows): format launcher encoding test

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-16 00:42:56 -07:00
Peter Steinberger
f81f9d8570 chore: enforce max-lines suppression ratchet (#107315)
* ci: enforce max-lines suppression ratchet

* chore: prune stale max-lines suppression

* fix: close max-lines ratchet enforcement gaps

* fix: harden max-lines ratchet checks

* fix(ci): satisfy max-lines ratchet checks

* style: format max-lines declarations

* fix(ci): match oxlint suppression grammar

* test: isolate max-lines git fixtures

* chore: prune resolved max-lines debt

* test: skip newline path fixture on Windows

* fix: harden max-lines suppression ratchet

* chore: refresh max-lines baseline

* fix: close max-lines ratchet bypasses

* fix: derive ratchet base from PR merge tree

* fix: support older Git in staged ratchet

* fix: align max-lines declarations and baseline

* chore: refresh max-lines baseline for current main

* fix: exclude generated wizard locales from max-lines

* chore: prune resolved max-lines debt
2026-07-14 09:27:02 -07:00
Vincent Koc
63c7c21bdf refactor(core): privatize new internal helpers (#107096) 2026-07-14 12:02:46 +08:00
Peter Steinberger
fe715a1b88 refactor(daemon): trim internal exports (#107075) 2026-07-13 20:43:08 -07:00
Peter Steinberger
d1684f48a3 refactor: delete dead infra and config exports (#106019)
* refactor: delete dead infra and config exports

* refactor: preserve live infra and config contracts

* refactor(config): remove obsolete file-store lifecycle APIs

* refactor(infra): finish current-main dead export cleanup
2026-07-13 12:00:47 -07:00
Peter Steinberger
db02a96c4c refactor(process): route bounded commands through Execa (#106495)
* refactor(process): centralize bounded command execution

* refactor(process): migrate core one-shot commands

* refactor(plugins): migrate one-shot commands

* fix(process): await Windows tree termination

* chore(plugin-sdk): refresh process runtime surface

* refactor(process): migrate remaining bounded commands

* refactor(process): normalize command result handling

* refactor(process): split execution responsibilities

* chore(plugin-sdk): refresh API baseline

* chore(process): remove release-owned changelog entry

* fix(process): narrow binary command input checks

* fix(process): cap sandbox command output

* fix(qa-lab): preserve exact node probe env

* chore(ci): refresh dead export baseline

* fix(process): preserve force-kill command deadlines

* fix(process): avoid post-exit timeout reclassification

* test(process): update scp staging wrapper mock

* test(process): update remaining wrapper mocks

* refactor(qa-lab): preserve Execa tar execution
2026-07-13 11:07:35 -07:00
Peter Steinberger
e2ec8283c4 refactor(deadcode): trim mid-size src exports (#105888)
* refactor(deadcode): trim auto-reply and CLI exports

* refactor(deadcode): trim cron and task exports

* refactor(deadcode): trim fleet and process exports

* test(deadcode): exercise live task and process seams

* test(fleet): cover stream redaction through owner module

* refactor(security): trim dead internal exports

* refactor(secrets): trim dead internal exports

* refactor(deadcode): trim remaining src exports

* refactor(deadcode): remove test-only runtime exports

* refactor(deadcode): trim pairing test exports

* refactor(deadcode): reconcile refreshed baseline

* test(auto-reply): deduplicate queue state imports
2026-07-13 00:42:56 -07:00
Peter Steinberger
6df498c3cd refactor: canonicalize binary operation results (#106049)
* refactor(normalization-core): promote shared result type

* refactor(agent-core): reuse canonical error coercion

* refactor: discriminate internal operation results

* docs: establish shared result convention

* fix(agent-core): preserve error coercion facade

* build: derive package entries from exports

* fix(plugins): resolve shared result subpath

* fix(ci): align Result integration guards

* build: refresh plugin SDK API baseline

* fix(agent-core): preserve toError compatibility
2026-07-13 00:39:43 -07:00
Vincent Koc
f33ab243cf fix(sqlite): reject runtimes vulnerable to WAL corruption (#106065)
* fix(sqlite): require WAL-reset-safe Node runtime

* docs(sqlite): document safe Node runtime floor

* fix(sqlite): defer runtime library validation until use

* fix(ci): align startup memory with Node 24.15
2026-07-13 13:59:00 +08:00
Peter Steinberger
1aff6da827 refactor(test): use shared timeout helper (#105918) 2026-07-12 20:51:51 -07:00
Peter Steinberger
1b313dc4d4 chore(tooling): enforce indexed access in core tests (#105375)
* test(tooling): enforce indexed access in core tests

* test(tui): constrain theme environment overrides

* test(doctor): enforce indexed access in migration fixtures
2026-07-12 14:29:52 +01:00
Peter Steinberger
ae14fc1e81 fix: harden Crestodian maintenance flows (#105153)
* fix: harden Crestodian maintenance flows

* fix: skip trajectories for ephemeral Crestodian plans

* test: satisfy Crestodian CI gates
2026-07-12 09:51:03 +01:00
Peter Steinberger
6b95f98fe7 fix(core): make indexed access explicit across remaining src (NUIA phase 3b) (#104773)
* fix(core): make indexed access explicit in auto-reply, infra, and config

Part 1/3 of the src NUIA phase-3b burn-down (#104600): iteration and
destructuring over index reads, boundary guards on parsed input, and
named invariants. Config path walkers bind the path head once; SQLite
migration key handling is hoisted without query-shape changes.

* fix(core): make indexed access explicit in cli, gateway, commands, security, shared

Part 2/3: argv/token selection restructured, gateway event/attachment
invariants named, security parsers stay fail-closed (invariant
violations throw), edit-distance matrices access checked entries.

* fix(core): make indexed access explicit across remaining src surfaces

Part 3/3: channels, plugins, process, cron, plugin-sdk, media, logging,
tui, hooks, daemon, and small directories. Latent bug fixed: a tailnet
resolver could leak undefined through a string|null contract and now
fails with a descriptive local error.

* fix(core): keep optional boundaries optional after per-commit review

Review findings: expectDefined misused where absence is a legitimate
state. CLI --profile/route-args missing next tokens take their existing
miss paths; help normalization compares --help against the last
positional again; first-time plugin install spreads absent cfg.plugins;
denylist scan iterates manifest dependency entries instead of throwing
on omitted sections; tailnet resolver returns a guaranteed string at
the source instead of a caller-side undefined throw.

* refactor(core): closed-key provider labels and honest optional passthroughs

PROVIDER_LABELS becomes a satisfies-typed closed record (static reads
provably defined; dynamic lookups go through providerUsageLabel with
honest string|undefined). Status-scan overview passes its optional
params through unchanged instead of asserting them.

* fix(channels): make getChatChannelMeta honestly optional

The original signature claimed ChatChannelMeta while leaking undefined
on bundled channel id metadata drift; three of four callers already
handled absence. The return type now says so, and the one assuming
caller falls back to the raw channel label.

* fix(core): index-safety for post-rebase main drift

Covers the sqlite-sessions flip and auth-source-plan code that landed
mid-phase, plus the channel-validation test consuming the now honestly
optional getChatChannelMeta.

* refactor(channels): split chat-meta accessors along the SDK contract

getChatChannelMeta keeps its shipped plugin-SDK signature (defined for
bundled ids, fail-loud on impossible misses); new findChatChannelMeta
carries the drift-tolerant optional contract for core auto-enable and
formatting paths.

* fix(qa-channel): own channel metadata instead of a guaranteed-undefined catalog lookup

qa-channel spread getChatChannelMeta over an id that is never in the
bundled catalog, shipping an empty setup meta by accident; the fail-loud
SDK accessor exposed it. The channel now declares its metadata once.

* fix(gateway): heartbeat projection lookahead is optional at the transcript tail

expectDefined wrapped messages[i + 1] whose absence on the final message
is the normal case; the adjacent ternary already handled it. Restores
the plain optional read with an explicit guard in the pair condition.

* fix(plugin-sdk): channel plugin factory tolerates non-bundled channel ids again

createChannelPluginBase spreads bundled catalog meta for ANY channel id,
where absence is the normal case for external plugins; the resolver is
honestly optional again while the exported bundled-id accessor keeps the
fail-loud contract.

* fix(core): spreads of optional config sections stay optional

Fresh-setup and first-install paths (crestodian setup inference, hook
installs, agent config base, target agent models) legitimately lack the
section being rebuilt; spreading undefined is the shipped {} semantics.
Removes the remaining gratuitous assertion wraps found by tree audit.
2026-07-11 20:47:34 -07:00
Andi Liao
410e6db74c fix(status): avoid false shell-wrapper audit warnings (#81778) 2026-07-11 18:12:32 +08:00
Peter Steinberger
394bd1b489 fix: make LaunchAgent plists launchd-readable (#104228) 2026-07-11 00:12:48 -07:00
Peter Steinberger
b4428fb9df fix(nodes): keep Gateway connections healthy and consistent (#103093)
* fix(gateway): evict unresponsive node sockets

Co-authored-by: hoangsaga123 <hoangsaga123@gmail.com>

* fix(nodes): align invoke timeout semantics

* fix(node): preserve managed connection settings

* docs(changelog): note node connection fixes

* fix(node): redact service credentials in status

* fix(systemd): preserve escaped operator values

* fix(node): carry explicit plaintext service mode

* fix(systemd): avoid promoting stale shell references

* fix(node): clear fingerprints for plaintext runs

* docs(changelog): defer node notes to release

* fix(nodes): normalize forwarded system run timeout

* fix(systemd): preserve operator environment values

* fix(nodes): type normalized invoke payload

---------

Co-authored-by: hoangsaga123 <hoangsaga123@gmail.com>
2026-07-09 22:48:25 +01:00
tayoun
4f9a371c95 fix(launchd): verify profile updater jobs by metadata (#97264)
* fix(launchd): verify profile updater jobs by metadata

* fix(launchd): bind updater proof to job metadata

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 16:55:23 +01:00
Peter Steinberger
5ef269c2bb fix: keep bounded Unicode text valid across UTF-16 boundaries (#102823)
* fix(text): keep bounded output UTF-16 safe

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>
Co-authored-by: 0668000539 <shu.zongyu@xydigit.com>
Co-authored-by: 张鹊平0668001085 <zhang.queping@xydigit.com>
Co-authored-by: 赵旺0668001248 <zhao.wang1@xydigit.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: lizeyu-xydt <li.zeyu@xydigit.com>

* chore(changelog): defer release note to automation

* refactor(qa-lab): keep text helper behind SDK

---------

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>
Co-authored-by: 0668000539 <shu.zongyu@xydigit.com>
Co-authored-by: 张鹊平0668001085 <zhang.queping@xydigit.com>
Co-authored-by: 赵旺0668001248 <zhao.wang1@xydigit.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: lizeyu-xydt <li.zeyu@xydigit.com>
2026-07-09 15:21:23 +01:00
Vincent Koc
c8d95da14c refactor: localize file-private exports (#101701) 2026-07-07 06:57:19 -07:00
Santiago
80bb0cd24e fix: include pnpm 11 bins in gateway PATH (#85238)
* fix: include pnpm 11 bins in gateway PATH

* fix: include pnpm 11 bins in gateway PATH

* fix(security): reject workspace package-manager PATH roots

* fix(infra): preserve package paths from root cwd

---------

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 22:49:21 -07:00
Ashd.LW.
70c2e837cd fix(gateway): show last error when status probe fails (#95902)
* fix(gateway): show last error when status probe fails

* fix(gateway): scope status log diagnostics

---------

Co-authored-by: wAngByg <wAngByg@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 22:22:19 -07:00
Peter Steinberger
dbba3d2a8e fix(ci): stabilize Windows startup fallback tests (#101223)
* test(windows): stabilize startup fallback fixtures

* ci(windows): route daemon scheduler changes
2026-07-07 00:37:50 +01:00
Peter Steinberger
bab9952801 test(windows): isolate fallback ownership models 2026-07-06 19:28:02 -04:00
Peter Steinberger
bb44c2311d fix(windows): repair legacy gateway fallback updates (#101213)
* fix(windows): repair doctor update fallback migration

* fix(windows): remove hidden startup fallback launchers

* fix(windows): preserve recovered gateway tokens

* fix(windows): harden update fallback migration

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(windows): capture fallback runtime before task rewrite

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(windows): complete legacy update restart handoff

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(windows): verify fallback ownership during migration

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(windows): honor update restart policy during repair

* fix(windows): wait for task takeover evidence

* fix(windows): preserve fallback after direct task launch

* fix(windows): preserve repaired task identity

* fix(windows): snapshot gateway before repair

* fix: scope update service repair ownership

* style: satisfy update lint checks

* fix: restart gateways stopped during updates

* fix(windows): enforce fallback process takeover

* fix(windows): prove fallback ownership during takeover

* fix(windows): verify process exit during takeover

* fix(windows): wait through fallback reloads

* fix(windows): harden fallback takeover ownership

* fix(windows): type takeover preflight inputs

* fix(windows): recognize booting replacement task

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* chore: leave changelog release-owned

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-07 00:09:48 +01:00
Peter Steinberger
a13a198a4b fix(update): guard Windows task autostart during package updates (#100757)
* fix(update): guard Windows task autostart

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix(update): preserve recovery error causes

* fix(update): retain restore failure causes

* fix(update): recover task on Ctrl+Break

* chore(update): document aggregate lint intent

* fix(update): tolerate deleted Windows tasks

* fix(update): preserve combined recovery failures

* fix(update): preserve aggregate error causes

* fix(update): construct aggregate causes consistently

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 10:33:47 +01:00
mushuiyu886
08852d2bf7 fix #98107: Gateway regenerates service-env file on every restart, wiping Telegram bot tokens (#99124)
* Preserve LaunchAgent env-file SecretRefs

* fix gateway start repair env source preservation

* test(daemon): cover SecretRef ownership cleanup

Co-authored-by: mushuiyu886 <mushuiyu886@users.noreply.github.com>

* fix(daemon): preserve only active SecretRefs

Co-authored-by: 杨浩宇0668001029 <yang.haoyu@xydigit.com>

* chore: defer service SecretRefs changelog

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: mushuiyu886 <mushuiyu886@users.noreply.github.com>
2026-07-06 02:24:39 +01:00
Peter Steinberger
33f7c17f23 [codex] Fallback when Windows gateway task exits early (#76245)
* fix(windows): bound clean scheduler exits before fallback

* test(windows): cover scheduled task startup fallback

* test(windows): assert startup fallback is not running
2026-07-05 08:19:33 -07:00
Peter Steinberger
614e87cce1 chore: update dependencies (#100027) 2026-07-04 14:56:50 -04:00
Jason (Json)
cccc856b82 fix: reject incompatible Node 23 runtimes (#99832)
* fix: reject incompatible Node 23 runtimes

* fix: repair installer CI coverage

* docs: clarify supported Node ranges

* fix: fail closed on unreadable runtime versions

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-04 00:03:49 -07:00