fix(chat): honor [skills] enabled=false at runtime#663
Conversation
Closes #655. SkillsConfig.enabled was documented and defaulted to true in the schema but never consulted at runtime — skills were always discovered and injected into the LLM prompt. Add a discover_skills_if_enabled helper that short-circuits to an empty Vec when the flag is false, and route all chat.rs discovery callsites through it so operators who set `[skills] enabled = false` get zero skills in the prompt. Entire-Checkpoint: f3c67e202c0b
Greptile SummaryThis PR fixes #655 by adding a Confidence Score: 5/5Safe to merge — the fix is correct, both code arms are tested, and prior review concerns are resolved. All four callsites correctly route through the new helper; the semaphore replaces the forbidden Mutex<()>; the redundant discover_and_load() in the model-probe path was cleaned up in the final commit. No P0/P1 issues remain. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[chat request arrives] --> B{send / model-probe / persona path}
B --> C[call discover_skills_if_enabled\n&config]
C --> D{config.skills.enabled?}
D -- false --> E[return Vec::new\nno skills injected into prompt]
D -- true --> F[FsSkillDiscoverer::default_paths\nmoltis_config::data_dir]
F --> G[FsSkillDiscoverer::discover]
G --> H{discover result}
H -- Ok --> I[return Vec of SkillMetadata]
H -- Err --> J[warn! + return Vec::new]
I --> K[inject into system prompt\navailable_skills block]
E --> L[skip available_skills block]
Reviews (3): Last reviewed commit: "fix(chat): reuse existing config in cont..." | Re-trigger Greptile |
Per CLAUDE.md "mutex must guard actual state", a bare `Mutex<()>` is forbidden. The tests only need serialization of the global data_dir override, not guarded state — use `tokio::sync::Semaphore` with a single permit, which is the idiomatic serialization primitive. Addresses Greptile P2 feedback on #663. Entire-Checkpoint: 76d5468681db
Merging this PR will not alter performance
Comparing Footnotes
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
The model-probe/context path already loads `moltis_config::discover_and_load()` into a local `config` binding; the skill discovery call was loading it a second time unnecessarily. Reuse the existing binding. Addresses Greptile P2 feedback on #663. Entire-Checkpoint: f63026f15bae
Summary
Closes #655.
SkillsConfig.enabledis documented and defaulted totruein the schema (crates/config/src/schema.rs:1275), but the runtime never consulted it —FsSkillDiscoverer::default_paths()was invoked unconditionally from every chat.rs callsite, so every discoveredSKILL.mdlanded in the system prompt regardless of[skills] enabled = false. This is the same failure mode as #638 / #639: schema promises behavior the code doesn't deliver.discover_skills_if_enabled(&MoltisConfig)helper incrates/chat/src/lib.rsthat returnsVec::new()whenconfig.skills.enabledisfalse, otherwise delegates toFsSkillDiscoverer.FsSkillDiscovererusages insideLiveChatService(send path, model-probe path, and the twoload_prompt_persona_for_sessionpaths) through the helper. The first two thread a freshmoltis_config::discover_and_load()(matching surrounding patterns); the other two reuse the already-loadedpersona.config.Non-chat callsites (
cli,gateway/services,gateway/server,skills/watcher,tools/skill_tools,httpd/server) are intentionally out of scope — they don't inject skills into the LLM prompt. Can be a follow-up if full coverage is desired.Validation
Completed
cargo check -p moltis-chatcargo +nightly-2025-11-30 fmt --all -- --checkcargo +nightly-2025-11-30 clippy -p moltis-chat -p moltis-config -p moltis-skills --all-targets -- -D warningscargo test -p moltis-chat --lib→ 175 passed, 0 failed (includes two new regression tests)Remaining
just lint(full Darwin clippy sweep)just test(full test suite)./scripts/local-validate.sh <PR>Manual QA
moltis.toml:SKILL.mdunder<data_dir>/skills/test-skill/SKILL.md.<available_skills>block.<available_skills>entries. Flipenabled = trueand confirm the skill reappears.Tests
Two new
#[tokio::test]s incrates/chat/src/lib.rs:discover_skills_if_enabled_short_circuits_when_disabled— plants a realSKILL.mdunder a tempdata_dirand asserts the helper returns an empty list whenenabled = false, proving we don't fall through to the filesystem.discover_skills_if_enabled_runs_discoverer_when_enabled— the complementary arm, asserting the planted skill is discovered whenenabled = true.Tests share a module-local
tokio::sync::Mutexso they serialize their mutations to the globalmoltis_config::set_data_diroverride.