fix(skill): auto-generate crystallizer summary/steps instead of rejecting - #2253
Merged
Hun-ger merged 1 commit intoAug 26, 2026
Conversation
…ting defaultDraftValidator threw skill.crystallize.invalid: missing summary / missing steps whenever the LLM returned valid JSON without those fields (observed with deepseek-v4-flash), flooding bridge logs every 5-10s and stalling the crystallizer queue. It now repairs the draft instead: - missing summary: derived from first step body/title, then displayTitle, then name, then a static placeholder; capped at 200 chars - missing steps: a single Execute-the-fix step generated from the summary; only throws when nothing at all can be derived - missing name: still rejected (normaliseDraft already supplies a name fallback on the LLM path, so this only guards direct validator use) Fixes MemTensor#2143
Collaborator
✅ Automated Test Results: PASSEDAll tests passed (15/15 executed). memos_local_plugin/unit: 15/15. Duration: 4s Branch: |
Hun-ger
merged commit Aug 26, 2026
7b130ef
into
MemTensor:fix-local-plugin-260824
2 of 3 checks passed
15 tasks
syzsunshine219
added a commit
that referenced
this pull request
Aug 28, 2026
## Description This PR consolidates the local-plugin reliability fixes developed and validated on `fix-local-plugin-260824`. ### Highlights - hardens Hermes bridge process detection, PID/status reconciliation, installer rollback, Windows-native provider behavior, and UTF-8 tool output; - makes secret environment fallback explicit and wires first-class `maxTokens` / `headers` configuration through the L3 and Skill Evolver clients; - moves idle-skill archival off the foreground path with bounded, atomic lifecycle work; - recovers useful crystallizer drafts when LLM output omits derivable fields; - bounds startup-recovery shutdown and adds the newest-trace index with collision-safe migration handling; - resolves DeepSeek Harness auxiliary reasoning capability from exact model metadata, with per-route TTL caching, concurrent lookup coalescing, adapter-update invalidation, and registration-bound race fallback. Contribution history is preserved from #2192, #2209, #2246, #2248, #2252, #2253, #2256, and #2284. The capability-driven implementation supersedes the negative probe cache proposed in #2285. No new runtime dependencies are introduced. Related Issue (Required): Fixes #2278 Reviewers: @hijzy @whipser030 ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) - [x] Refactor (does not change functionality, e.g. code style improvements, linting) - [x] Documentation update ## How Has This Been Tested? - [x] Unit Test - `npm run test:unit -- --reporter=dot`: 179 files passed; 1,549 tests passed and 2 skipped. - `npm exec vitest run tests/unit/adapters/deepseek-harness-*.test.ts -- --reporter=dot`: 65/65 passed. - `python3 apps/memos-local-plugin/tests/python/test_hermes_provider_pipeline.py`: 36/36 passed. - [x] Test Script Or Test Steps - `npm run lint` - `npm run build:package` - `npm run check:hermes-version` - Ruff 0.11.8 check and format verification for both changed Python files. - Packed commit `d76c78aa` and installed the identical tarball into DSH `0.1.0-rc.6` `web` profiles on macOS and Windows. - Verified SHA-256 `61e805f862acbe0873581e22cac4592ab0a9ff4d23d607a5f9fac5df93e80253` on both hosts. - Verified unsupported-reasoning routes issue zero rejected `off` probes across repeated/concurrent calls, supported routes retain `off`, adapter invalidation refreshes the capability, and both installed profiles start with healthy Host LLM bridges. - [x] Pipeline Automated API Test - GitHub CI will run after PR creation. > Note: `make format` could not start because Poetry is not installed on the validation host. The equivalent Ruff 0.11.8 checks for the changed Python files passed. ## Checklist - [x] I have performed a self-review of my own code | 我已自行检查了自己的代码 - [x] I have commented my code in hard-to-understand areas | 我已在难以理解的地方对代码进行了注释 - [x] I have added tests that prove my fix is effective or that my feature works | 我已添加测试以证明我的修复有效或功能正常 - [x] I have created related documentation issue/PR in [MemOS-Docs](https://github.com/MemTensor/MemOS-Docs) (if applicable) | N/A: no external documentation change is required. - [x] I have linked the issue to this PR (if applicable) | 我已将 issue 链接到此 PR - [x] I have mentioned the person who will review this PR | 我已提及将审查此 PR 的人 ## Reviewer Checklist - [x] closes #2278 - [x] Made sure Checks passed locally; GitHub CI will run on creation - [x] Tests have been provided
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
defaultDraftValidatorincore/skill/crystallize.tsthrowsskill.crystallize.invalid: missing summary/missing stepswhenever the LLM returns valid JSON that omits those fields. With deepseek-v4-flash this happens routinely, flooding bridge logs with 10+ERROR skill.crystallize.failedmessages per minute and stalling the crystallizer queue (which in turn delays other RPCs likememory.searchwaiting on the queue to drain).This PR makes the validator repair such drafts instead of rejecting them:
displayTitle→name→ static placeholder"skill procedure". Capped at 200 chars. Never throws for a missing/empty summary."Execute the fix"step generated from the summary (title+body, capped at 2000 chars). Only throws when nothing at all can be derived.skill.crystallize.invalid: missing name). On the LLM path this is unreachable anyway —normaliseDraft()already substitutesskill_<policy_id>— so the check remains purely a guard for direct validator use.Change
core/skill/crystallize.ts—defaultDraftValidatorrewritten: strict → lenient repair (uses||not??— LLM JSON emits empty strings, and??only falls through on null/undefined).tests/unit/skill/crystallize.test.ts— the old "rejects drafts that the validator flags as invalid" test used{ steps: [], summary: "" }, which is exactly the case this PR now repairs; converted into an end-to-end regression asserting the draft crystallizes with auto-generated summary + steps.tests/unit/skill/crystallize-validator.test.ts— new focused suite (8 tests): full-draft passthrough, never-throws-for-missing-summary, summary fallback chain (step body → displayTitle → name), 200-char cap, empty-string (||) semantics, single-step auto-generation, missing-name rejection.Tests
npx vitest run tests/unit/skill→ 54 passed (10 files)npx tsc -p tsconfig.json --noEmit→ clean (exit 0)missing summaryrejections since).Related
Type of change
How Has This Been Tested?
npx vitest run tests/unit/skill— 54 passed)tsc --noEmitclean)skill.crystallize.failedmissing-summary floods dropped to zero)Checklist