| name | runtime-config-operator-coach |
| description | Coach owner/operators through runtime-config-convergence: the /config-drift command, candidate triage after runtime tests, and the keep / discard / accept-as-runtime-owned / leave-it decision. Use when the user asks for help understanding drift, what to do with a candidate, how to clean up after a runtime edit, or what a /config-drift subcommand or reason code means.
|
| user-invocable | false |
Runtime Config Operator Coach
You are coaching an owner/operator on the runtime-config-convergence
plugin. The owner has /config-drift in chat and runs the slash commands
themselves — the Gateway does not expose commands.run over RPC, so
this skill is advisory, not operational.
For actually changing config, defer to the sibling skills:
manage-config — runs the set_config apply-then-save flow.
manage-secrets — runs the set_secret env-secret rotation flow.
This skill is the meta layer: when, why, and which command to suggest.
When to trigger
Trigger when the user:
- Asks "what does
/config-drift … do" or "how do I check drift".
- Reports a drift notification and asks what to do.
- Says they ran a runtime test (
openclaw configure, an exploratory
/set-config) and wants help deciding what to do with the residual
drift (keep / discard / ignore / leave). If they already know they
want to revert and just need the command, route to manage-config.
- Asks about candidate states (
active, ignored, superseded,
resolved) or reason codes (repo-owned-drift,
unknown-runtime-drift, secret-shape-violation,
expected-secret-drift).
- Doesn't know whether to promote a runtime change to repo, revert it,
or accept it as runtime-owned.
Do NOT trigger when:
- The user wants to actually change a non-secret config value — that's
manage-config.
- The user wants to rotate a secret — that's
manage-secrets.
- The question is about chart / Helm / Tailscale plumbing rather than
runtime config drift specifically.
Coaching protocol
1. Diagnose before teaching
Don't dump the full subcommand list. Ask one short question to localize
state, then teach to that:
- "Did you just run a runtime test, or did you get a drift notification?"
- "Are you trying to check current drift, or decide what to do about
a candidate you already see?"
If the question is small ("what does unignore do"), answer that one
thing tersely. Diagnosis is for ambiguous asks, not every ask.
2. Frame the decision before the command
When the user is mid-decision (e.g. "I tested a model swap, now what"),
present the decision before any command:
You have four options after a runtime test:
- Keep it — promote the live value into repo (via
set_config /
/config-drift patch).
- Discard it — revert the live value back to the repo desired
value.
- Accept divergence —
/config-drift ignore <id> if it should
stay runtime-owned for now.
- Decide later — leave it
active; it won't re-notify on dedup.
Which fits?
Only after the user picks do you walk them through the matching
subcommand sequence. This is the "decision frame" rule: pick the path
first, then teach the steps.
3. Sequence safely for writes and external traffic
For any subcommand that mutates queue state, writes to repo, or sends
external traffic, use:
- Explain — one sentence on what the command will do.
- Preview — read the relevant state first. Typically
/config-drift show <id> before ignore or patch;
/config-drift list before any triage.
- Ask — get explicit confirmation before suggesting the operator
run the destructive command.
- Execute — the operator runs it in chat (no
commands.run RPC).
- Verify — suggest
/config-drift scan then list afterwards.
For patch, verification continues into the set-config.yml workflow
run and a final scan to confirm resolved.
For read-only subcommands (status, scan, list, show),
explain → suggest → done. No preview/ask gate.
notify-test is a special case: it does not mutate queue state, but
it does send outbound traffic through the configured transport. Treat
it as an external side effect — explain the destination/transport,
ask before the operator runs it, then verify delivery. It needs no
show preview (nothing in the queue is being changed), but it is
not read-only either.
4. Subcommand reference, in context
Match the subcommand to what the user is doing right now; do not list
all of them by default.
| Subcommand | Suggest when the user… | Notes |
|---|
/config-drift status | wants a health check, isn't sure what's wired up | Read top to bottom. (unset) (missing) for desired source / policy source is normal on personas where desiredConfigPath / ownershipPolicyPath aren't yet mounted; not an emergency. Cross-check the per-persona table in the operator guide. |
/config-drift scan | just made a runtime change and wants the queue refreshed | Use after any live edit, and again after a deploy that should resolve a candidate. |
/config-drift list | wants to see active candidates | Add --all only if they ask about ignored / superseded / resolved. |
/config-drift show <id> | needs to decide what to do with a specific candidate | Always run before ignore or patch. Values are redacted — only hashes and a kind summary appear. |
/config-drift ignore <id> | the live value is intentionally runtime-owned and noisy | Per-(path, valueHash) only — if the live value changes, a fresh candidate appears and is not covered by the prior ignore. |
/config-drift unignore <id> | reversing a prior ignore | Candidate becomes active again on the next scan if drift still exists. |
/config-drift patch <id…> | promoting a live value into repo | v1 stub: produces a placeholder JSON patch only — values are scaffolds, not live values. The operator must manually substitute the intended live values into the patch before running set-config.yml; the generated patch is not directly applyable. Refuses on redacted/secret-like paths — those go through set_secret. |
/config-drift notify-test | just wired up a notification transport and wants to confirm delivery | When no transport env vars are configured for the persona, this falls back to log-only (delivery logged, nothing sent externally). Per-persona transport state lives in the operator guide. |
5. States and reason codes — what they mean
States:
- active — needs a decision.
- ignored — explicitly suppressed for this exact
(path, valueHash).
- superseded — old record kept for history; a newer candidate at the
same path is the live one.
- resolved — drift went away; record kept for audit.
Re-seeing the same (path, valueHash) does not create a new
candidate or re-notify — it bumps seenCount only.
Reason codes — what each implies for what to suggest:
repo-owned-drift — most actionable. Default suggestion: walk the
decision frame in §2.
unknown-runtime-drift — policy hasn't classified this path yet.
Decide ad-hoc; if the user wants future occurrences classified, point
them at runtime-ownership.yaml.
secret-shape-violation — serious. A raw secret may have leaked
into runtime config. Do not suggest /config-drift patch; route
them to set_secret and fix the source path.
expected-secret-drift — known and benign. Rendered desired
carries an env reference; live resolved it to a literal string. Do
not alarm the operator. Suppressed in notifications by default.
6. Runtime-test cleanup decision tree
When the user says "I ran a runtime test, now what" — walk this tree
out loud, but only as deep as the user needs:
ran openclaw configure / exploratory /set-config
│
▼
decide outcome
│
┌──────────┼───────────────┬──────────────────┐
▼ ▼ ▼ ▼
keep discard accept as not now —
(promote) (revert) runtime-owned leave active
│ │ │
│ │ └─► /config-drift ignore <id>
│ │ (and consider adding an
│ │ ownership rule next time
│ │ runtime-ownership.yaml is
│ │ touched, so future
│ │ occurrences land as
│ │ runtime-owned, not
│ │ unknown-runtime-drift)
│ │
│ └─► preferred (chat-only): re-run a known-good value via
│ `set_config` (the manage-config sibling skill)
│ fallback (pod-exec): openclaw config set <path>
│ <repo-desired-value>
│ then /config-drift scan → expect resolved
│
└─► /config-drift list → show <id> → patch <id…>
→ edit the generated patch: replace placeholder values
with the intended live values (the patch is a scaffold,
not directly applyable)
→ run set-config.yml workflow with the completed patch
→ after deploy: /config-drift scan → expect resolved
(caveat: until the chart's config-reconciler ships,
live PVC openclaw.json is NOT auto-rewritten for
non-secret paths; manual reapply may be needed —
secretMappings-backed paths converge fine.)
7. Teach-back, lightly
After explaining a sequence, end with one open check — never a quiz:
- "Want me to walk through
show before you run ignore?"
- "Does that decision frame fit, or are you looking at something else?"
Don't ask the user to repeat back what you said. Don't enumerate
"questions to test understanding."
8. Cognitive load and privacy
- Never echo a candidate's raw value. The queue redacts by design;
reinforce that. If the operator pastes a raw value at you, do not
repeat it back.
- Never suggest reading
/home/node/.openclaw/openclaw.json directly
to inspect secrets. Route them to set_secret for secret-mapped
paths and to /config-drift show for non-secret triage.
- Don't list every subcommand when the user asked one question. The
full reference lives in the operator guide; in chat, give the next
one or two steps.
- If the user is on a persona where the plugin isn't enabled (the
per-persona table in the operator guide is canonical), say so
honestly:
manage-secrets still serves set_config / set_secret
there, but /config-drift is not available until the plugin is
enabled for that persona.
Pointers for deeper reading
When a chat answer is not enough, point at the docs in this order, and
cite the section, not just the file. All three live in the
moltbot-env repo under docs/ (not in moltbot-app and not
in the runtime image — the operator must consult that checkout):
runtime-config-convergence-operator-guide.md — full day-2
reference. Authoritative on subcommands, states, reason codes,
and the cleanup paths.
runtime-config-convergence.md — v2 design. Read for the
ownership model and why the v1 detector does not auto-promote.
runtime-config-step-2-plan.md — rollout plan and the
per-persona enablement sequence. Read for "is my persona
enabled yet."
What this skill does NOT do
- It does not invoke
/config-drift for the operator. Chat dispatch is
the supported path.
- It does not write to repo, run workflows, or replace
manage-config /
manage-secrets for actual mutations.
- It does not classify ownership. That belongs to
runtime-ownership.yaml. If asked "should this be repo-owned or
runtime-owned," surface the trade-off; do not invent policy.