Problem
Skill keyword enrichment runs as a fire-and-forget Task.Run() in SystemSkillSyncService.RescanAndUpdateIndex() (line 330). Sessions that start before enrichment completes get no keyword matches because the _enrichedKeywords dictionary in SkillRegistry is empty for those skills.
Root Cause
SystemSkillSyncService.StartAsync() calls RescanAndUpdateIndex() synchronously
RescanAndUpdateIndex() registers skills in the registry and updates the skill index
- Enrichment is fired as
_ = Task.Run(() => EnrichAllSkillsAsync()) — no await
- The daemon is ready to accept Slack events immediately
- First user message arrives →
MatchByKeywords() → skill not in _enrichedKeywords → skipped
The enrichment process hits the LLM for each skill (with a 30s timeout per skill). With 6 system skills, enrichment can take 30-180 seconds. Any session started during this window gets no auto-loaded skills.
Mitigating Factor
The keyword cache (~/.netclaw/skills/.system-keywords/) means enrichment only hits the LLM on first run or after skill content changes. Cached keywords load instantly. But after a fresh install, version upgrade, or cache invalidation, the race window is wide.
Expected Behavior
Skills should be usable from the moment the daemon accepts connections. Options:
- Block startup until enrichment completes (but this conflicts with "never blocks startup")
- Use fallback keywords immediately, upgrade to enriched keywords when ready — currently, if
_chatClientProvider is available, fallback keywords are NOT applied (line 328-350). Only the else branch applies fallbacks.
- Apply fallback keywords first, then enrich in background — best of both worlds
Relevant Code
SystemSkillSyncService.cs:316-351 — RescanAndUpdateIndex() fire-and-forget
SystemSkillSyncService.cs:516-544 — ApplyFallbackKeywords (only used when no provider)
SkillRegistry.cs:91-149 — MatchByKeywords skips un-enriched skills (line 113-114)
Incidents
Session D0AC6CKBK5K/1774023557.531309 (0.7.1) could not load any skills on first interaction.
Problem
Skill keyword enrichment runs as a fire-and-forget
Task.Run()inSystemSkillSyncService.RescanAndUpdateIndex()(line 330). Sessions that start before enrichment completes get no keyword matches because the_enrichedKeywordsdictionary inSkillRegistryis empty for those skills.Root Cause
SystemSkillSyncService.StartAsync()callsRescanAndUpdateIndex()synchronouslyRescanAndUpdateIndex()registers skills in the registry and updates the skill index_ = Task.Run(() => EnrichAllSkillsAsync())— no awaitMatchByKeywords()→ skill not in_enrichedKeywords→ skippedThe enrichment process hits the LLM for each skill (with a 30s timeout per skill). With 6 system skills, enrichment can take 30-180 seconds. Any session started during this window gets no auto-loaded skills.
Mitigating Factor
The keyword cache (
~/.netclaw/skills/.system-keywords/) means enrichment only hits the LLM on first run or after skill content changes. Cached keywords load instantly. But after a fresh install, version upgrade, or cache invalidation, the race window is wide.Expected Behavior
Skills should be usable from the moment the daemon accepts connections. Options:
_chatClientProvideris available, fallback keywords are NOT applied (line 328-350). Only theelsebranch applies fallbacks.Relevant Code
SystemSkillSyncService.cs:316-351—RescanAndUpdateIndex()fire-and-forgetSystemSkillSyncService.cs:516-544—ApplyFallbackKeywords(only used when no provider)SkillRegistry.cs:91-149—MatchByKeywordsskips un-enriched skills (line 113-114)Incidents
Session
D0AC6CKBK5K/1774023557.531309(0.7.1) could not load any skills on first interaction.