A merged PR may require knowledge-base updates. Review the change and update library/ as needed.
Source PR
- PR: #304 - feat: live config reload — settings and keys apply without restart
- Author: @thenotoriousllama
- Merged into:
main
- Files changed: 25
PR description
What
The SP-1 class fix for the boot-snapshot family (ISS-001 / ISS-005, plus the ISS-003 stale-tenancy secondary): settings and secrets changes now take effect without a daemon restart.
Originally stacked on #300 (fix/portkey-fail-closed) because this work builds directly on its no_model fail-closed state and vault validation; rebased onto main after #300 was squash-merged (all of #300's surfaces are now in main verbatim).
The four fixes (one commit each)
1. feat(pipeline): per-job live extraction gate — stop collapsing 'auto'→'none' at boot (ISS-001)
buildPipelineWorker no longer runs resolveEffectiveExtractionProvider at boot; the sentinel stays 'auto' in the running config.
- The extraction stage evaluates
isExtractionEnabled(config, providerConfiguredNow) per job via a new injectable ExtractionGateProbe (src/daemon/runtime/pipeline/reload.ts): a live master-enabled cell + a TTL-debounced (~1s) names-only secret-presence probe (listSecretNames — no decrypt, fail-closed on a store error), mirroring the mtime/TTL discipline documented in src/daemon/storage/live-reload.ts. Worst case: ~one listing per second.
resolveCredentialSecretNames (model-client-factory) derives WHICH names matter — PORTKEY_API_KEY with the gateway on, else the agent.yaml accounts' ${SECRET_REF} names — mirroring the boot providerConfigured signal exactly.
- Regression matrix covered: explicit provider still runs unconditionally; explicit
'none' still opts out; 'auto' + no key stays fail-closed; gate-less callers (unit/pure-config) are byte-identical.
2. feat(daemon): PipelineReloadSeam — settings/secret writes rebuild the inference client live (ISS-001/ISS-005)
- One unbound, debounced (~1s trailing-edge) seam created at assembly;
start() binds it to the pipeline build's reload closure. Fire-and-forget — never blocks an HTTP response; a burst of settings writes coalesces int
Files touched
.claude-plugin/marketplace.json (+2/-2)
.claude-plugin/plugin.json (+1/-1)
CHANGELOG.md (+4/-0)
harnesses/claude-code/.claude-plugin/plugin.json (+1/-1)
harnesses/codex/package.json (+1/-1)
harnesses/openclaw/openclaw.plugin.json (+1/-1)
harnesses/openclaw/package.json (+1/-1)
package-lock.json (+2/-2)
package.json (+1/-1)
src/daemon/runtime/assemble.ts (+201/-25)
src/daemon/runtime/dashboard/actions-api.ts (+35/-13)
src/daemon/runtime/inference/model-client-factory.ts (+29/-0)
src/daemon/runtime/pipeline/config.ts (+11/-5)
src/daemon/runtime/pipeline/extraction.ts (+18/-3)
src/daemon/runtime/pipeline/index.ts (+15/-0)
src/daemon/runtime/pipeline/reload.ts (+287/-0)
src/daemon/runtime/projects/onboarding-api.ts (+10/-2)
src/daemon/runtime/secrets/api.ts (+17/-0)
src/daemon/runtime/vault/api.ts (+37/-0)
tests/daemon/runtime/dashboard/actions-api.test.ts (+60/-3)
tests/daemon/runtime/pipeline/extraction-live-gate.test.ts (+144/-0)
tests/daemon/runtime/pipeline/reload.test.ts (+315/-0)
tests/daemon/runtime/projects/onboarding-live-tenancy.test.ts (+137/-0)
tests/daemon/runtime/secrets/reload-trigger.test.ts (+125/-0)
tests/daemon/runtime/vault/settings-reload-trigger.test.ts (+152/-0)
Auto-generated by .github/workflows/kb-issue-on-merge.yaml on merge.
A merged PR may require knowledge-base updates. Review the change and update
library/as needed.Source PR
mainPR description
What
The SP-1 class fix for the boot-snapshot family (ISS-001 / ISS-005, plus the ISS-003 stale-tenancy secondary): settings and secrets changes now take effect without a daemon restart.
The four fixes (one commit each)
1.
feat(pipeline): per-job live extraction gate — stop collapsing'auto'→'none'at boot (ISS-001)buildPipelineWorkerno longer runsresolveEffectiveExtractionProviderat boot; the sentinel stays'auto'in the running config.isExtractionEnabled(config, providerConfiguredNow)per job via a new injectableExtractionGateProbe(src/daemon/runtime/pipeline/reload.ts): a live master-enabledcell + a TTL-debounced (~1s) names-only secret-presence probe (listSecretNames— no decrypt, fail-closed on a store error), mirroring the mtime/TTL discipline documented insrc/daemon/storage/live-reload.ts. Worst case: ~one listing per second.resolveCredentialSecretNames(model-client-factory) derives WHICH names matter —PORTKEY_API_KEYwith the gateway on, else theagent.yamlaccounts'${SECRET_REF}names — mirroring the bootproviderConfiguredsignal exactly.'none'still opts out;'auto'+ no key stays fail-closed; gate-less callers (unit/pure-config) are byte-identical.2.
feat(daemon):PipelineReloadSeam— settings/secret writes rebuild the inference client live (ISS-001/ISS-005)start()binds it to the pipeline build's reload closure. Fire-and-forget — never blocks an HTTP response; a burst of settings writes coalesces intFiles touched
.claude-plugin/marketplace.json(+2/-2).claude-plugin/plugin.json(+1/-1)CHANGELOG.md(+4/-0)harnesses/claude-code/.claude-plugin/plugin.json(+1/-1)harnesses/codex/package.json(+1/-1)harnesses/openclaw/openclaw.plugin.json(+1/-1)harnesses/openclaw/package.json(+1/-1)package-lock.json(+2/-2)package.json(+1/-1)src/daemon/runtime/assemble.ts(+201/-25)src/daemon/runtime/dashboard/actions-api.ts(+35/-13)src/daemon/runtime/inference/model-client-factory.ts(+29/-0)src/daemon/runtime/pipeline/config.ts(+11/-5)src/daemon/runtime/pipeline/extraction.ts(+18/-3)src/daemon/runtime/pipeline/index.ts(+15/-0)src/daemon/runtime/pipeline/reload.ts(+287/-0)src/daemon/runtime/projects/onboarding-api.ts(+10/-2)src/daemon/runtime/secrets/api.ts(+17/-0)src/daemon/runtime/vault/api.ts(+37/-0)tests/daemon/runtime/dashboard/actions-api.test.ts(+60/-3)tests/daemon/runtime/pipeline/extraction-live-gate.test.ts(+144/-0)tests/daemon/runtime/pipeline/reload.test.ts(+315/-0)tests/daemon/runtime/projects/onboarding-live-tenancy.test.ts(+137/-0)tests/daemon/runtime/secrets/reload-trigger.test.ts(+125/-0)tests/daemon/runtime/vault/settings-reload-trigger.test.ts(+152/-0)Auto-generated by
.github/workflows/kb-issue-on-merge.yamlon merge.